83#include "llvm/IR/IntrinsicsARM.h"
118#define DEBUG_TYPE "arm-isel"
121STATISTIC(NumMovwMovt,
"Number of GAs materialized with movw + movt");
122STATISTIC(NumLoopByVals,
"Number of loops generated for byval arguments");
124 "Number of constants with their storage promoted into constant pools");
128 cl::desc(
"Enable / disable ARM interworking (for debugging only)"),
133 cl::desc(
"Enable / disable promotion of unnamed_addr constants into "
138 cl::desc(
"Maximum size of constant to promote into a constant pool"),
142 cl::desc(
"Maximum size of ALL constants to promote into a constant pool"),
147 cl::desc(
"Maximum interleave factor for MVE VLDn to generate."),
152 cl::desc(
"Maximum number of base-updates to check generating postindex."),
160 ARM::R0, ARM::R1, ARM::R2, ARM::R3
174void ARMTargetLowering::addTypeForNEON(
MVT VT,
MVT PromotedLdStVT) {
175 if (VT != PromotedLdStVT) {
184 if (ElemTy != MVT::f64)
188 if (ElemTy == MVT::i32) {
232void ARMTargetLowering::addDRTypeForNEON(
MVT VT) {
234 addTypeForNEON(VT, MVT::f64);
237void ARMTargetLowering::addQRTypeForNEON(
MVT VT) {
239 addTypeForNEON(VT, MVT::v2f64);
242void ARMTargetLowering::setAllExpand(
MVT VT) {
255void ARMTargetLowering::addAllExtLoads(
const MVT From,
const MVT To,
262void ARMTargetLowering::addMVEVectorTypes(
bool HasMVEFP) {
263 const MVT IntTypes[] = { MVT::v16i8, MVT::v8i16, MVT::v4i32 };
265 for (
auto VT : IntTypes) {
340 const MVT FloatTypes[] = { MVT::v8f16, MVT::v4f32 };
341 for (
auto VT : FloatTypes) {
415 const MVT LongTypes[] = { MVT::v2i64, MVT::v2f64 };
416 for (
auto VT : LongTypes) {
433 addAllExtLoads(MVT::v8i16, MVT::v8i8,
Legal);
434 addAllExtLoads(MVT::v4i32, MVT::v4i16,
Legal);
435 addAllExtLoads(MVT::v4i32, MVT::v4i8,
Legal);
452 for (
auto VT : {MVT::v8i8, MVT::v4i8, MVT::v4i16}) {
461 const MVT pTypes[] = {MVT::v16i1, MVT::v8i1, MVT::v4i1, MVT::v2i1};
462 for (
auto VT : pTypes) {
513 RegInfo(Subtarget->getRegisterInfo()),
514 Itins(Subtarget->getInstrItineraryData()) {
520 const Triple &TT = TM.getTargetTriple();
522 if (Subtarget->isThumb1Only())
527 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only() &&
528 Subtarget->hasFPRegs()) {
537 if (!Subtarget->hasVFP2Base()) {
538 setAllExpand(MVT::f32);
544 if (!Subtarget->hasFP64()) {
545 setAllExpand(MVT::f64);
555 if (Subtarget->hasFullFP16()) {
570 if (Subtarget->hasBF16()) {
572 setAllExpand(MVT::bf16);
573 if (!Subtarget->hasFullFP16())
585 addAllExtLoads(VT, InnerVT,
Expand);
594 if (!Subtarget->isThumb1Only() && !Subtarget->hasV8_1MMainlineOps())
597 if (!Subtarget->hasV8_1MMainlineOps())
600 if (!Subtarget->isThumb1Only())
609 if (Subtarget->hasMVEIntegerOps())
610 addMVEVectorTypes(Subtarget->hasMVEFloatOps());
613 if (Subtarget->hasLOB()) {
617 if (Subtarget->hasNEON()) {
618 addDRTypeForNEON(MVT::v2f32);
619 addDRTypeForNEON(MVT::v8i8);
620 addDRTypeForNEON(MVT::v4i16);
621 addDRTypeForNEON(MVT::v2i32);
622 addDRTypeForNEON(MVT::v1i64);
624 addQRTypeForNEON(MVT::v4f32);
625 addQRTypeForNEON(MVT::v2f64);
626 addQRTypeForNEON(MVT::v16i8);
627 addQRTypeForNEON(MVT::v8i16);
628 addQRTypeForNEON(MVT::v4i32);
629 addQRTypeForNEON(MVT::v2i64);
631 if (Subtarget->hasFullFP16()) {
632 addQRTypeForNEON(MVT::v8f16);
633 addDRTypeForNEON(MVT::v4f16);
636 if (Subtarget->hasBF16()) {
637 addQRTypeForNEON(MVT::v8bf16);
638 addDRTypeForNEON(MVT::v4bf16);
642 if (Subtarget->hasMVEIntegerOps() || Subtarget->hasNEON()) {
682 if (Subtarget->hasNEON()) {
795 if (!Subtarget->hasVFP4Base()) {
804 for (
MVT Ty : {MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v4i16, MVT::v2i16,
813 for (
auto VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v16i8, MVT::v8i16,
822 if (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) {
830 if (Subtarget->hasMVEIntegerOps()) {
835 if (Subtarget->hasMVEFloatOps()) {
839 if (!Subtarget->hasFP64()) {
885 if (!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) {
888 if (Subtarget->hasFullFP16()) {
896 if (!Subtarget->hasFP16()) {
925 if (!Subtarget->isThumb1Only()) {
944 if (TT.isTargetAEABI() && !Subtarget->allowsUnalignedMem()) {
956 if (!Subtarget->isThumb1Only()) {
963 if (Subtarget->hasDSP()) {
973 if (Subtarget->hasBaseDSP()) {
981 if (Subtarget->isThumb1Only()) {
985 if (Subtarget->isThumb1Only() || !Subtarget->hasV6Ops()
986 || (Subtarget->isThumb2() && !Subtarget->hasDSP()))
1001 if (Subtarget->hasMVEIntegerOps())
1005 if (Subtarget->isThumb1Only()) {
1011 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops())
1025 if (!Subtarget->hasV5TOps() || Subtarget->isThumb1Only()) {
1034 if (Subtarget->hasPerfMon())
1038 if (!Subtarget->hasV6Ops())
1041 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
1042 : Subtarget->hasDivideInARMMode();
1049 if (TT.isOSWindows() && !Subtarget->hasDivideInThumbMode()) {
1061 if (TT.isTargetAEABI() || TT.isAndroid() || TT.isTargetGNUAEABI() ||
1062 TT.isTargetMuslAEABI() || TT.isOSFuchsia() || TT.isOSWindows()) {
1065 HasStandaloneRem =
false;
1092 if (TT.isOSWindows())
1099 InsertFencesForAtomic =
false;
1100 if (Subtarget->hasAnyDataBarrier() &&
1101 (!Subtarget->isThumb() || Subtarget->hasV8MBaselineOps())) {
1105 if (!Subtarget->isThumb() || !Subtarget->isMClass())
1110 if (!Subtarget->hasAcquireRelease() ||
1113 InsertFencesForAtomic =
true;
1119 if (Subtarget->hasDataBarrier())
1120 InsertFencesForAtomic =
true;
1140 if (!InsertFencesForAtomic) {
1147 if (TT.isOSLinux() || (!Subtarget->isMClass() && Subtarget->hasV6Ops())) {
1159 }
else if ((Subtarget->isMClass() && Subtarget->hasV8MBaselineOps()) ||
1160 Subtarget->hasForced32BitAtomics()) {
1174 if (!Subtarget->hasV6Ops()) {
1180 if (!Subtarget->useSoftFloat() && Subtarget->hasFPRegs() &&
1181 !Subtarget->isThumb1Only()) {
1210 if (Subtarget->hasFullFP16()) {
1220 if (Subtarget->hasFullFP16())
1235 if (!Subtarget->useSoftFloat() && Subtarget->hasVFP2Base() &&
1236 !Subtarget->isThumb1Only()) {
1243 if (!Subtarget->hasVFP4Base()) {
1249 if (!Subtarget->useSoftFloat() && !Subtarget->isThumb1Only()) {
1251 if (!Subtarget->hasFPARMv8Base() || !Subtarget->hasFP64()) {
1259 if (!Subtarget->hasFP16()) {
1279 if (Subtarget->hasFPARMv8Base()) {
1289 if (Subtarget->hasFP64())
1293 if (Subtarget->hasNEON()) {
1303 if (Subtarget->hasFullFP16()) {
1340 if (Subtarget->hasNEON()) {
1352 if (Subtarget->hasV8Ops()) {
1362 if (Subtarget->hasFullFP16()) {
1385 if (TT.isOSWindows()) {
1402 if (Subtarget->hasMVEIntegerOps())
1405 if (Subtarget->hasV6Ops())
1407 if (Subtarget->isThumb1Only())
1410 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) ||
1411 Subtarget->isThumb2()) {
1417 if (Subtarget->useSoftFloat() || Subtarget->isThumb1Only() ||
1418 !Subtarget->hasVFP2Base() || Subtarget->hasMinSize())
1440 Align(1ULL << Subtarget->getPreferBranchLogAlignment()));
1448 return Subtarget->useSoftFloat();
1452 return !Subtarget->isThumb1Only() && VT.
getSizeInBits() <= 32;
1465std::pair<const TargetRegisterClass *, uint8_t>
1476 case MVT::f32:
case MVT::f64:
case MVT::v8i8:
case MVT::v4i16:
1477 case MVT::v2i32:
case MVT::v1i64:
case MVT::v2f32:
1478 RRC = &ARM::DPRRegClass;
1483 if (Subtarget->useNEONForSinglePrecisionFP())
1486 case MVT::v16i8:
case MVT::v8i16:
case MVT::v4i32:
case MVT::v2i64:
1487 case MVT::v4f32:
case MVT::v2f64:
1488 RRC = &ARM::DPRRegClass;
1492 RRC = &ARM::DPRRegClass;
1496 RRC = &ARM::DPRRegClass;
1500 return std::make_pair(RRC,
Cost);
1509 if ((Subtarget->hasMVEIntegerOps() &&
1510 (VT == MVT::v2i64 || VT == MVT::v4i32 || VT == MVT::v8i16 ||
1511 VT == MVT::v16i8)) ||
1512 (Subtarget->hasMVEFloatOps() &&
1513 (VT == MVT::v2f64 || VT == MVT::v4f32 || VT == MVT::v8f16)))
1527 if (Subtarget->hasNEON()) {
1528 if (VT == MVT::v4i64)
1529 return &ARM::QQPRRegClass;
1530 if (VT == MVT::v8i64)
1531 return &ARM::QQQQPRRegClass;
1533 if (Subtarget->hasMVEIntegerOps()) {
1534 if (VT == MVT::v4i64)
1535 return &ARM::MQQPRRegClass;
1536 if (VT == MVT::v8i64)
1537 return &ARM::MQQQQPRRegClass;
1546 Align &PrefAlign)
const {
1553 (Subtarget->hasV6Ops() && !Subtarget->isMClass() ?
Align(8) :
Align(4));
1565 unsigned NumVals =
N->getNumValues();
1569 for (
unsigned i = 0; i != NumVals; ++i) {
1570 EVT VT =
N->getValueType(i);
1571 if (VT == MVT::Glue || VT == MVT::Other)
1577 if (!
N->isMachineOpcode())
1585 if (
MCID.getNumDefs() == 0)
1587 if (!Itins->isEmpty() &&
1588 Itins->getOperandCycle(
MCID.getSchedClass(), 0) > 2U)
1602 return Const->getZExtValue() == 16;
1610 return Const->getZExtValue() == 16;
1618 return Const->getZExtValue() == 16;
1687 bool isVarArg)
const {
1706 if (!
getTM().isAAPCS_ABI())
1708 else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1716 if (!
getTM().isAAPCS_ABI()) {
1717 if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() && !isVarArg)
1720 }
else if (Subtarget->hasFPRegs() && !Subtarget->isThumb1Only() &&
1729 bool isVarArg)
const {
1730 return CCAssignFnForNode(CC,
false, isVarArg);
1734 bool isVarArg)
const {
1735 return CCAssignFnForNode(CC,
true, isVarArg);
1742 bool isVarArg)
const {
1743 switch (getEffectiveCallingConv(CC, isVarArg)) {
1769 if (Subtarget->hasFullFP16()) {
1770 Val = DAG.
getNode(ARMISD::VMOVhr, dl, ValVT, Val);
1782 if (Subtarget->hasFullFP16()) {
1783 Val = DAG.
getNode(ARMISD::VMOVrh, dl,
1796SDValue ARMTargetLowering::LowerCallResult(
1800 SDValue ThisVal,
bool isCmseNSCall)
const {
1808 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
1809 CCValAssign VA = RVLocs[i];
1813 if (i == 0 && isThisReturn) {
1815 "unexpected return calling convention register assignment");
1833 if (!Subtarget->isLittle())
1835 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1850 if (!Subtarget->isLittle())
1852 Val = DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
1882 const ISD::InputArg &Arg = Ins[VA.
getValNo()];
1893std::pair<SDValue, MachinePointerInfo> ARMTargetLowering::computeAddrForCallArg(
1895 bool IsTailCall,
int SPDiff)
const {
1897 MachinePointerInfo DstInfo;
1917 return std::make_pair(DstAddr, DstInfo);
1926ARMTargetLowering::ByValCopyKind ARMTargetLowering::ByValNeedsCopyForTailCall(
1939 if (!SrcFrameIdxNode || !DstFrameIdxNode)
1942 int SrcFI = SrcFrameIdxNode->getIndex();
1943 int DstFI = DstFrameIdxNode->getIndex();
1945 "byval passed in non-fixed stack slot");
1967 if (SrcOffset == DstOffset)
1975 RegsToPassVector &RegsToPass,
1982 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
1983 unsigned id = Subtarget->isLittle() ? 0 : 1;
1995 MachinePointerInfo DstInfo;
1996 std::tie(DstAddr, DstInfo) =
1997 computeAddrForCallArg(dl, DAG, NextVA, StackPtr, IsTailCall, SPDiff);
2014 SelectionDAG &DAG = CLI.
DAG;
2016 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2017 SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2018 SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2025 const CallBase *CB = CLI.
CB;
2028 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2030 MachineFunction::CallSiteInfo CSInfo;
2031 bool isStructRet = (Outs.
empty()) ?
false : Outs[0].Flags.isSRet();
2032 bool isThisReturn =
false;
2033 bool isCmseNSCall =
false;
2034 bool isSibCall =
false;
2035 bool PreferIndirect =
false;
2036 bool GuardWithBTI =
false;
2046 !Subtarget->noBTIAtReturnTwice())
2054 isCmseNSCall =
true;
2057 if (!Subtarget->supportsTailCall())
2073 PreferIndirect = Subtarget->isThumb() && Subtarget->hasMinSize() &&
2074 count_if(GV->users(), [&BB](
const User *U) {
2075 return isa<Instruction>(U) &&
2076 cast<Instruction>(U)->getParent() == BB;
2083 IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
2097 "site marked musttail");
2100 unsigned NumBytes = CCInfo.getStackSize();
2109 if (isTailCall && !isSibCall) {
2110 auto FuncInfo = MF.
getInfo<ARMFunctionInfo>();
2111 unsigned NumReusableBytes = FuncInfo->getArgumentStackSize();
2116 assert(StackAlign &&
"data layout string is missing stack alignment");
2117 NumBytes =
alignTo(NumBytes, *StackAlign);
2122 SPDiff = NumReusableBytes - NumBytes;
2126 if (SPDiff < 0 && AFI->getArgRegsSaveSize() < (
unsigned)-SPDiff)
2142 RegsToPassVector RegsToPass;
2151 DenseMap<unsigned, SDValue> ByValTemporaries;
2155 for (
const CCValAssign &VA : ArgLocs) {
2157 SDValue Src = OutVals[ArgIdx];
2158 ISD::ArgFlagsTy
Flags = Outs[ArgIdx].Flags;
2160 if (!
Flags.isByVal())
2164 MachinePointerInfo DstInfo;
2165 std::tie(Dst, DstInfo) =
2166 computeAddrForCallArg(dl, DAG, VA,
SDValue(),
true, SPDiff);
2167 ByValCopyKind
Copy = ByValNeedsCopyForTailCall(DAG, Src, Dst, Flags);
2169 if (Copy == NoCopy) {
2174 }
else if (Copy == CopyOnce) {
2178 ByValTemporaries[ArgIdx] = Src;
2180 assert(Copy == CopyViaTemp &&
"unexpected enum value");
2184 int TempFrameIdx = MFI.CreateStackObject(
2185 Flags.getByValSize(),
Flags.getNonZeroByValAlign(),
false);
2193 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2194 SDValue Ops[] = {Chain, Temp, Src, SizeNode, AlignNode};
2196 DAG.
getNode(ARMISD::COPY_STRUCT_BYVAL, dl, VTs,
Ops));
2197 ByValTemporaries[ArgIdx] = Temp;
2200 if (!ByValCopyChains.
empty())
2210 bool AfterFormalArgLoads =
false;
2214 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
2216 ++i, ++realArgIdx) {
2217 CCValAssign &VA = ArgLocs[i];
2218 SDValue Arg = OutVals[realArgIdx];
2219 ISD::ArgFlagsTy
Flags = Outs[realArgIdx].Flags;
2220 bool isByVal =
Flags.isByVal();
2240 if (isTailCall && VA.
isMemLoc() && !AfterFormalArgLoads) {
2242 if (ByValTempChain) {
2247 for (
unsigned I = 0;
I < OutVals.
size(); ++
I) {
2248 if (Outs[
I].
Flags.isByVal())
2256 FrameIndexSDNode *FIN =
2261 if (!MFI.isFixedObjectIndex(FIN->
getIndex()))
2264 for (
const CCValAssign &VA : ArgLocs) {
2272 if (!IncomingLoad.
empty()) {
2280 AfterFormalArgLoads =
true;
2292 auto ArgVT = Outs[realArgIdx].ArgVT;
2293 if (isCmseNSCall && (ArgVT == MVT::f16)) {
2311 PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
2312 StackPtr, MemOpChains, isTailCall, SPDiff);
2316 PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
2317 StackPtr, MemOpChains, isTailCall, SPDiff);
2321 MachinePointerInfo DstInfo;
2322 std::tie(DstAddr, DstInfo) =
2323 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2327 PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
2328 StackPtr, MemOpChains, isTailCall, SPDiff);
2330 if (realArgIdx == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
2331 Outs[0].VT == MVT::i32) {
2333 "unexpected calling convention register assignment");
2335 "unexpected use of 'returned'");
2336 isThisReturn =
true;
2341 RegsToPass.push_back(std::make_pair(VA.
getLocReg(), Arg));
2342 }
else if (isByVal) {
2344 unsigned offset = 0;
2348 unsigned ByValArgsCount = CCInfo.getInRegsParamsCount();
2349 unsigned CurByValIdx = CCInfo.getInRegsParamsProcessed();
2352 bool NeedsStackCopy;
2353 if (
auto It = ByValTemporaries.
find(realArgIdx);
2354 It != ByValTemporaries.
end()) {
2355 ByValSrc = It->second;
2356 NeedsStackCopy =
true;
2359 NeedsStackCopy = !isTailCall;
2363 if (CurByValIdx < ByValArgsCount) {
2364 unsigned RegBegin, RegEnd;
2365 CCInfo.getInRegsParamInfo(CurByValIdx, RegBegin, RegEnd);
2369 for (i = 0, j = RegBegin;
j < RegEnd; i++,
j++) {
2373 DAG.
getLoad(PtrVT, dl, Chain, AddArg, MachinePointerInfo(),
2376 RegsToPass.push_back(std::make_pair(j, Load));
2381 offset = RegEnd - RegBegin;
2383 CCInfo.nextInRegsParam();
2388 if (NeedsStackCopy &&
Flags.getByValSize() > 4 * offset) {
2391 MachinePointerInfo DstInfo;
2392 std::tie(Dst, DstInfo) =
2393 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2401 SDVTList VTs = DAG.
getVTList(MVT::Other, MVT::Glue);
2402 SDValue Ops[] = { Chain, Dst, Src, SizeNode, AlignNode};
2409 MachinePointerInfo DstInfo;
2410 std::tie(DstAddr, DstInfo) =
2411 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2418 if (!MemOpChains.
empty())
2424 for (
const auto &[
Reg,
N] : RegsToPass) {
2432 bool isDirect =
false;
2435 const Triple &
TT = TM.getTargetTriple();
2436 const GlobalValue *GVal =
nullptr;
2438 GVal =
G->getGlobal();
2439 bool isStub = !TM.shouldAssumeDSOLocal(GVal) &&
TT.isOSBinFormatMachO();
2441 bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->isMClass());
2442 bool isLocalARMFunc =
false;
2445 if (Subtarget->genLongCalls()) {
2447 "long-calls codegen is not position independent!");
2452 if (Subtarget->genExecuteOnly()) {
2453 if (Subtarget->useMovt())
2465 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2471 const char *Sym = S->getSymbol();
2473 if (Subtarget->genExecuteOnly()) {
2474 if (Subtarget->useMovt())
2486 Addr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Addr);
2493 if (!PreferIndirect) {
2498 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !
ARMInterworking);
2500 if (isStub && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2501 assert(
TT.isOSBinFormatMachO() &&
"WrapperPIC use on non-MachO?");
2503 ARMISD::WrapperPIC, dl, PtrVt,
2510 }
else if (Subtarget->isTargetCOFF()) {
2511 assert(Subtarget->isTargetWindows() &&
2512 "Windows is the only supported COFF target");
2516 else if (!TM.shouldAssumeDSOLocal(GVal))
2523 DAG.
getNode(ARMISD::Wrapper, dl, PtrVt, Callee),
2532 const char *Sym = S->getSymbol();
2533 if (isARMFunc && Subtarget->isThumb1Only() && !Subtarget->hasV5TOps()) {
2535 ARMConstantPoolValue *CPV =
2537 ARMPCLabelIndex, 4);
2539 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
2544 Callee = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVt, Callee, PICLabel);
2551 assert(!isARMFunc && !isDirect &&
2552 "Cannot handle call to ARM function or direct call");
2556 "call to non-secure function would require "
2557 "passing arguments on stack",
2563 "call to non-secure function would return value through pointer",
2570 if (Subtarget->isThumb()) {
2572 CallOpc = ARMISD::t2CALL_BTI;
2573 else if (isCmseNSCall)
2574 CallOpc = ARMISD::tSECALL;
2575 else if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
2576 CallOpc = ARMISD::CALL_NOLINK;
2578 CallOpc = ARMISD::CALL;
2580 if (!isDirect && !Subtarget->hasV5TOps())
2581 CallOpc = ARMISD::CALL_NOLINK;
2582 else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() &&
2584 !Subtarget->hasMinSize())
2586 CallOpc = ARMISD::CALL_NOLINK;
2588 CallOpc = isLocalARMFunc ? ARMISD::CALL_PRED : ARMISD::CALL;
2595 if (isTailCall && !isSibCall) {
2600 std::vector<SDValue>
Ops;
2601 Ops.push_back(Chain);
2602 Ops.push_back(Callee);
2610 for (
const auto &[
Reg,
N] : RegsToPass)
2614 const uint32_t *
Mask;
2615 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
2623 isThisReturn =
false;
2629 assert(Mask &&
"Missing call preserved mask for calling convention");
2633 Ops.push_back(InGlue);
2646 Chain = DAG.
getNode(CallOpc, dl, {MVT::Other, MVT::Glue},
Ops);
2657 uint64_t CalleePopBytes =
2660 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, dl);
2666 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
2667 InVals, isThisReturn,
2668 isThisReturn ? OutVals[0] :
SDValue(), isCmseNSCall);
2675void ARMTargetLowering::HandleByVal(
CCState *State,
unsigned &
Size,
2676 Align Alignment)
const {
2678 Alignment = std::max(Alignment,
Align(4));
2684 unsigned AlignInRegs = Alignment.
value() / 4;
2685 unsigned Waste = (ARM::R4 -
Reg) % AlignInRegs;
2686 for (
unsigned i = 0; i < Waste; ++i)
2692 unsigned Excess = 4 * (ARM::R4 -
Reg);
2699 if (NSAAOffset != 0 &&
Size > Excess) {
2711 unsigned ByValRegBegin =
Reg;
2712 unsigned ByValRegEnd = std::min<unsigned>(
Reg +
Size / 4, ARM::R4);
2716 for (
unsigned i =
Reg + 1; i != ByValRegEnd; ++i)
2722 Size = std::max<int>(
Size - Excess, 0);
2730bool ARMTargetLowering::IsEligibleForTailCallOptimization(
2736 const SmallVectorImpl<ISD::OutputArg> &Outs = CLI.
Outs;
2737 const SmallVectorImpl<SDValue> &OutVals = CLI.
OutVals;
2738 const SmallVectorImpl<ISD::InputArg> &Ins = CLI.
Ins;
2739 const SelectionDAG &DAG = CLI.
DAG;
2744 assert(Subtarget->supportsTailCall());
2757 SmallSet<MCPhysReg, 5> AddressRegisters = {ARM::R0, ARM::R1, ARM::R2,
2759 if (!(Subtarget->isThumb1Only() ||
2760 MF.
getInfo<ARMFunctionInfo>()->shouldSignReturnAddress(
true)))
2761 AddressRegisters.
insert(ARM::R12);
2762 for (
const CCValAssign &AL : ArgLocs)
2764 AddressRegisters.
erase(
AL.getLocReg());
2765 if (AddressRegisters.
empty()) {
2766 LLVM_DEBUG(
dbgs() <<
"false (no reg to hold function pointer)\n");
2785 <<
" (guaranteed tail-call CC)\n");
2786 return CalleeCC == CallerCC;
2791 bool isCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
2793 if (isCalleeStructRet != isCallerStructRet) {
2806 const GlobalValue *GV =
G->getGlobal();
2809 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
2810 TT.isOSBinFormatMachO())) {
2819 getEffectiveCallingConv(CalleeCC, isVarArg),
2820 getEffectiveCallingConv(CallerCC, CallerF.
isVarArg()), MF,
C, Ins,
2827 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
2828 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
2829 if (CalleeCC != CallerCC) {
2830 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
2831 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) {
2840 const ARMFunctionInfo *AFI_Caller = MF.
getInfo<ARMFunctionInfo>();
2848 const MachineRegisterInfo &MRI = MF.
getRegInfo();
2850 LLVM_DEBUG(
dbgs() <<
"false (parameters in CSRs do not match)\n");
2869 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
2878 StringRef IntKind =
F.getFnAttribute(
"interrupt").getValueAsString();
2891 if (IntKind ==
"" || IntKind ==
"IRQ" || IntKind ==
"FIQ" ||
2894 else if (IntKind ==
"SWI" || IntKind ==
"UNDEF")
2898 "must be one of: IRQ, FIQ, SWI, ABORT or UNDEF");
2903 return DAG.
getNode(ARMISD::INTRET_GLUE,
DL, MVT::Other, RetOps);
2925 bool isLittleEndian = Subtarget->isLittle();
2928 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
2937 "secure entry function would return value through pointer",
2942 for (
unsigned i = 0, realRVLocIdx = 0;
2944 ++i, ++realRVLocIdx) {
2945 CCValAssign &VA = RVLocs[i];
2948 SDValue Arg = OutVals[realRVLocIdx];
2949 bool ReturnF16 =
false;
2951 if (Subtarget->hasFullFP16() &&
getTM().isTargetHardFloat()) {
2984 auto RetVT = Outs[realRVLocIdx].ArgVT;
3006 DAG.
getVTList(MVT::i32, MVT::i32), Half);
3010 HalfGPRs.
getValue(isLittleEndian ? 0 : 1), Glue);
3016 HalfGPRs.
getValue(isLittleEndian ? 1 : 0), Glue);
3028 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
3030 fmrrd.
getValue(isLittleEndian ? 0 : 1), Glue);
3035 fmrrd.
getValue(isLittleEndian ? 1 : 0), Glue);
3045 const ARMBaseRegisterInfo *
TRI = Subtarget->getRegisterInfo();
3071 !Subtarget->isMClass()) {
3072 if (Subtarget->isThumb1Only())
3079 return DAG.
getNode(RetNode, dl, MVT::Other, RetOps);
3082bool ARMTargetLowering::isUsedByReturnOnly(
SDNode *
N,
SDValue &Chain)
const {
3083 if (
N->getNumValues() != 1)
3085 if (!
N->hasNUsesOfValue(1, 0))
3089 SDNode *
Copy = *
N->user_begin();
3093 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3095 TCChain =
Copy->getOperand(0);
3096 }
else if (
Copy->getOpcode() == ARMISD::VMOVRRD) {
3097 SDNode *VMov =
Copy;
3099 SmallPtrSet<SDNode*, 2>
Copies;
3100 for (SDNode *U : VMov->
users()) {
3108 for (SDNode *U : VMov->
users()) {
3109 SDValue UseChain =
U->getOperand(0);
3117 if (
U->getOperand(
U->getNumOperands() - 1).getValueType() == MVT::Glue)
3125 if (!
Copy->hasOneUse())
3132 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3134 TCChain =
Copy->getOperand(0);
3139 bool HasRet =
false;
3140 for (
const SDNode *U :
Copy->users()) {
3141 if (
U->getOpcode() != ARMISD::RET_GLUE &&
3142 U->getOpcode() != ARMISD::INTRET_GLUE)
3154bool ARMTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
3155 if (!Subtarget->supportsTailCall())
3172 &&
"LowerWRITE_REGISTER called for non-i64 type argument.");
3188 EVT PtrVT =
Op.getValueType();
3198 if (Subtarget->genExecuteOnly()) {
3203 auto GV =
new GlobalVariable(
3210 return LowerGlobalAddress(GA, DAG);
3216 if (Subtarget->isThumb1Only())
3217 CPAlign = std::max(CPAlign,
Align(4));
3223 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, Res);
3230 if (Subtarget->genExecuteOnly() && !Subtarget->hasV8MBaselineOps())
3239 unsigned ARMPCLabelIndex = 0;
3245 if (!IsPositionIndependent) {
3248 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
3255 CPAddr = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, CPAddr);
3259 if (!IsPositionIndependent)
3262 return DAG.
getNode(ARMISD::PIC_ADD,
DL, PtrVT, Result, PICLabel);
3290ARMTargetLowering::LowerGlobalTLSAddressDarwin(
SDValue Op,
3293 "This function expects a Darwin target");
3298 SDValue DescAddr = LowerGlobalAddressDarwin(
Op, DAG);
3304 MVT::i32,
DL, Chain, DescAddr,
3319 auto ARI =
static_cast<const ARMRegisterInfo *
>(
TRI);
3328 Chain, FuncTLVGet, DAG.
getRegister(ARM::R0, MVT::i32),
3334ARMTargetLowering::LowerGlobalTLSAddressWindows(
SDValue Op,
3337 "Windows specific TLS lowering");
3361 TLSArray = DAG.
getLoad(PtrVT,
DL, Chain, TLSArray, MachinePointerInfo());
3369 TLSIndex = DAG.
getNode(ARMISD::Wrapper,
DL, PtrVT, TLSIndex);
3370 TLSIndex = DAG.
getLoad(PtrVT,
DL, Chain, TLSIndex, MachinePointerInfo());
3376 MachinePointerInfo());
3383 DAG.
getNode(ARMISD::Wrapper,
DL, MVT::i32,
3396 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3398 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3400 ARMConstantPoolValue *CPV =
3411 Argument = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Argument, PICLabel);
3418 TargetLowering::CallLoweringInfo CLI(DAG);
3423 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3424 return CallResult.first;
3433 const GlobalValue *GV = GA->
getGlobal();
3439 SDValue ThreadPointer = DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3443 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3446 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3447 ARMConstantPoolValue *CPV =
3454 PtrVT, dl, Chain,
Offset,
3462 PtrVT, dl, Chain,
Offset,
3467 ARMConstantPoolValue *CPV =
3472 PtrVT, dl, Chain,
Offset,
3488 if (
TT.isOSDarwin())
3489 return LowerGlobalTLSAddressDarwin(
Op, DAG);
3491 if (
TT.isOSWindows())
3492 return LowerGlobalTLSAddressWindows(
Op, DAG);
3495 assert(
TT.isOSBinFormatELF() &&
"Only ELF implemented here");
3501 return LowerToTLSGeneralDynamicModel(GA, DAG);
3504 return LowerToTLSExecModels(GA, DAG, model);
3513 while (!Worklist.
empty()) {
3521 if (!
I ||
I->getParent()->getParent() !=
F)
3550 if (!GVar || !GVar->hasInitializer() ||
3551 !GVar->isConstant() || !GVar->hasGlobalUnnamedAddr() ||
3552 !GVar->hasLocalLinkage())
3557 auto *
Init = GVar->getInitializer();
3559 Init->needsDynamicRelocation())
3571 unsigned RequiredPadding = 4 - (
Size % 4);
3572 bool PaddingPossible =
3573 RequiredPadding == 4 || (CDAInit && CDAInit->isString());
3578 unsigned PaddedSize =
Size + ((RequiredPadding == 4) ? 0 : RequiredPadding);
3602 if (RequiredPadding != 4) {
3607 while (RequiredPadding--)
3619 ++NumConstpoolPromoted;
3620 return DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3625 if (!(GV = GA->getAliaseeObject()))
3628 return V->isConstant();
3637 return LowerGlobalAddressWindows(
Op, DAG);
3639 return LowerGlobalAddressELF(
Op, DAG);
3641 return LowerGlobalAddressDarwin(
Op, DAG);
3653 if (GV->
isDSOLocal() && !Subtarget->genExecuteOnly())
3666 }
else if (Subtarget->isROPI() && IsRO) {
3671 }
else if (Subtarget->isRWPI() && !IsRO) {
3674 if (Subtarget->useMovt()) {
3677 RelAddr = DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
G);
3679 ARMConstantPoolValue *CPV =
3682 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3696 if (Subtarget->useMovt() || Subtarget->genExecuteOnly()) {
3697 if (Subtarget->useMovt())
3701 return DAG.
getNode(ARMISD::Wrapper, dl, PtrVT,
3705 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3714 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3715 "ROPI/RWPI not currently supported for Darwin");
3720 if (Subtarget->useMovt())
3731 if (Subtarget->isGVIndirectSymbol(GV))
3740 "non-Windows COFF is not supported");
3741 assert(Subtarget->useMovt() &&
3742 "Windows on ARM expects to use movw/movt");
3743 assert(!Subtarget->isROPI() && !Subtarget->isRWPI() &&
3744 "ROPI/RWPI not currently supported for Windows");
3751 else if (!TM.shouldAssumeDSOLocal(GV))
3774 return DAG.
getNode(ARMISD::EH_SJLJ_SETJMP, dl,
3775 DAG.
getVTList(MVT::i32, MVT::Other),
Op.getOperand(0),
3776 Op.getOperand(1), Val);
3782 return DAG.
getNode(ARMISD::EH_SJLJ_LONGJMP, dl, MVT::Other,
Op.getOperand(0),
3789 return DAG.
getNode(ARMISD::EH_SJLJ_SETUP_DISPATCH, dl, MVT::Other,
3793SDValue ARMTargetLowering::LowerINTRINSIC_VOID(
3796 Op.getConstantOperandVal(
Op.getOperand(0).getValueType() == MVT::Other);
3800 case Intrinsic::arm_gnu_eabi_mcount: {
3806 const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
3807 const uint32_t *
Mask =
3809 assert(Mask &&
"Missing call preserved mask for calling convention");
3814 constexpr EVT ResultTys[] = {MVT::Other, MVT::Glue};
3818 if (Subtarget->isThumb())
3821 ARM::tBL_PUSHLR, dl, ResultTys,
3822 {ReturnAddress, DAG.getTargetConstant(ARMCC::AL, dl, PtrVT),
3823 DAG.getRegister(0, PtrVT), Callee, RegisterMask, Chain}),
3827 {ReturnAddress, Callee, RegisterMask, Chain}),
3836 unsigned IntNo =
Op.getConstantOperandVal(0);
3840 case Intrinsic::thread_pointer: {
3842 return DAG.
getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
3844 case Intrinsic::arm_cls: {
3848 const SDValue &Operand =
Op.getOperand(1);
3849 const EVT VTy =
Op.getValueType();
3852 case Intrinsic::arm_cls64: {
3858 case Intrinsic::arm_neon_vcls:
3859 case Intrinsic::arm_mve_vcls: {
3862 const EVT VTy =
Op.getValueType();
3865 case Intrinsic::eh_sjlj_lsda: {
3867 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
3872 unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
3873 ARMConstantPoolValue *CPV =
3877 CPAddr = DAG.
getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
3882 if (IsPositionIndependent) {
3884 Result = DAG.
getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel);
3888 case Intrinsic::arm_neon_vabs:
3891 case Intrinsic::arm_neon_vabds:
3892 if (
Op.getValueType().isInteger())
3894 Op.getOperand(1),
Op.getOperand(2));
3896 case Intrinsic::arm_neon_vabdu:
3898 Op.getOperand(1),
Op.getOperand(2));
3899 case Intrinsic::arm_neon_vmulls:
3900 case Intrinsic::arm_neon_vmullu: {
3901 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmulls)
3902 ? ARMISD::VMULLs : ARMISD::VMULLu;
3903 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3904 Op.getOperand(1),
Op.getOperand(2));
3906 case Intrinsic::arm_neon_vminnm:
3907 case Intrinsic::arm_neon_vmaxnm: {
3908 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminnm)
3910 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3911 Op.getOperand(1),
Op.getOperand(2));
3913 case Intrinsic::arm_neon_vminu:
3914 case Intrinsic::arm_neon_vmaxu: {
3915 if (
Op.getValueType().isFloatingPoint())
3917 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminu)
3919 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3920 Op.getOperand(1),
Op.getOperand(2));
3922 case Intrinsic::arm_neon_vmins:
3923 case Intrinsic::arm_neon_vmaxs: {
3925 if (!
Op.getValueType().isFloatingPoint()) {
3926 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
3928 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3929 Op.getOperand(1),
Op.getOperand(2));
3931 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
3933 return DAG.
getNode(NewOpc, SDLoc(
Op),
Op.getValueType(),
3934 Op.getOperand(1),
Op.getOperand(2));
3936 case Intrinsic::arm_neon_vtbl1:
3937 return DAG.
getNode(ARMISD::VTBL1, SDLoc(
Op),
Op.getValueType(),
3938 Op.getOperand(1),
Op.getOperand(2));
3939 case Intrinsic::arm_neon_vtbl2:
3940 return DAG.
getNode(ARMISD::VTBL2, SDLoc(
Op),
Op.getValueType(),
3941 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3942 case Intrinsic::arm_mve_pred_i2v:
3943 case Intrinsic::arm_mve_pred_v2i:
3944 return DAG.
getNode(ARMISD::PREDICATE_CAST, SDLoc(
Op),
Op.getValueType(),
3946 case Intrinsic::arm_mve_vreinterpretq:
3947 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, SDLoc(
Op),
Op.getValueType(),
3949 case Intrinsic::arm_mve_lsll:
3950 return DAG.
getNode(ARMISD::LSLL, SDLoc(
Op),
Op->getVTList(),
3951 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3952 case Intrinsic::arm_mve_asrl:
3953 return DAG.
getNode(ARMISD::ASRL, SDLoc(
Op),
Op->getVTList(),
3954 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3955 case Intrinsic::arm_mve_vsli:
3956 return DAG.
getNode(ARMISD::VSLIIMM, SDLoc(
Op),
Op->getVTList(),
3957 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3958 case Intrinsic::arm_mve_vsri:
3959 return DAG.
getNode(ARMISD::VSRIIMM, SDLoc(
Op),
Op->getVTList(),
3960 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
3971 if (!Subtarget->hasDataBarrier()) {
3975 assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() &&
3976 "Unexpected ISD::ATOMIC_FENCE encountered. Should be libcall!");
3977 return DAG.
getNode(ARMISD::MEMBARRIER_MCR, dl, MVT::Other,
Op.getOperand(0),
3987 }
else if (Subtarget->preferISHSTBarriers() &&
3996 DAG.
getConstant(Intrinsic::arm_dmb, dl, MVT::i32),
4004 (!Subtarget->
isThumb1Only() && Subtarget->hasV5TEOps())))
4006 return Op.getOperand(0);
4009 unsigned isRead =
~Op.getConstantOperandVal(2) & 1;
4011 (!Subtarget->hasV7Ops() || !Subtarget->hasMPExtension()))
4013 return Op.getOperand(0);
4015 unsigned isData =
Op.getConstantOperandVal(4);
4016 if (Subtarget->isThumb()) {
4018 isRead = ~isRead & 1;
4019 isData = ~isData & 1;
4022 return DAG.
getNode(ARMISD::PRELOAD, dl, MVT::Other,
Op.getOperand(0),
4037 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
4045 const SDLoc &dl)
const {
4047 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4049 const TargetRegisterClass *RC;
4051 RC = &ARM::tGPRRegClass;
4053 RC = &ARM::GPRRegClass;
4067 MVT::i32, dl, Root, FIN,
4073 if (!Subtarget->isLittle())
4075 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64, ArgValue, ArgValue2);
4088 const Value *OrigArg,
4089 unsigned InRegsParamRecordIdx,
4090 int ArgOffset,
unsigned ArgSize)
const {
4104 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4105 unsigned RBegin, REnd;
4110 RBegin = RBeginIdx == 4 ? (unsigned)ARM::R4 :
GPRArgRegs[RBeginIdx];
4115 ArgOffset = -4 * (ARM::R4 - RBegin);
4122 const TargetRegisterClass *RC =
4125 for (
unsigned Reg = RBegin, i = 0;
Reg < REnd; ++
Reg, ++i) {
4129 MachinePointerInfo(OrigArg, 4 * i));
4134 if (!MemOps.
empty())
4143 unsigned TotalArgRegsSaveSize,
4144 bool ForceMutable)
const {
4146 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4155 CCInfo.
getStackSize(), std::max(4U, TotalArgRegsSaveSize));
4159bool ARMTargetLowering::splitValueIntoRegisterParts(
4161 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID> CC)
const {
4163 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4175SDValue ARMTargetLowering::joinRegisterPartsIntoValue(
4177 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID> CC)
const {
4178 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4191SDValue ARMTargetLowering::LowerFormalArguments(
4198 ARMFunctionInfo *AFI = MF.
getInfo<ARMFunctionInfo>();
4207 unsigned CurArgIdx = 0;
4219 unsigned ArgRegBegin = ARM::R4;
4220 for (
const CCValAssign &VA : ArgLocs) {
4226 if (!
Flags.isByVal())
4230 unsigned RBegin, REnd;
4232 ArgRegBegin = std::min(ArgRegBegin, RBegin);
4238 int lastInsIndex = -1;
4242 ArgRegBegin = std::min(ArgRegBegin, (
unsigned)
GPRArgRegs[RegIdx]);
4245 unsigned TotalArgRegsSaveSize = 4 * (ARM::R4 - ArgRegBegin);
4249 for (
unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4250 CCValAssign &VA = ArgLocs[i];
4251 if (Ins[VA.
getValNo()].isOrigArg()) {
4252 std::advance(CurOrigArg,
4253 Ins[VA.
getValNo()].getOrigArgIndex() - CurArgIdx);
4254 CurArgIdx = Ins[VA.
getValNo()].getOrigArgIndex();
4265 GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4272 MVT::f64, dl, Chain, FIN,
4275 ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4283 ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4285 const TargetRegisterClass *RC;
4287 if (RegVT == MVT::f16 || RegVT == MVT::bf16)
4288 RC = &ARM::HPRRegClass;
4289 else if (RegVT == MVT::f32)
4290 RC = &ARM::SPRRegClass;
4291 else if (RegVT == MVT::f64 || RegVT == MVT::v4f16 ||
4292 RegVT == MVT::v4bf16)
4293 RC = &ARM::DPRRegClass;
4294 else if (RegVT == MVT::v2f64 || RegVT == MVT::v8f16 ||
4295 RegVT == MVT::v8bf16)
4296 RC = &ARM::QPRRegClass;
4297 else if (RegVT == MVT::i32)
4299 : &ARM::GPRRegClass;
4336 const ISD::InputArg &Arg = Ins[VA.
getValNo()];
4345 assert(VA.
getValVT() != MVT::i64 &&
"i64 should already be lowered");
4351 if (index != lastInsIndex)
4353 ISD::ArgFlagsTy
Flags = Ins[index].Flags;
4359 if (
Flags.isByVal()) {
4360 assert(Ins[index].isOrigArg() &&
4361 "Byval arguments cannot be implicit");
4365 CCInfo, DAG, dl, Chain, &*CurOrigArg, CurByValIndex,
4399 lastInsIndex = index;
4406 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.
getStackSize(),
4407 TotalArgRegsSaveSize);
4411 "secure entry function must not be variadic", dl.
getDebugLoc()));
4421 assert(StackAlign &&
"data layout string is missing stack alignment");
4422 StackArgSize =
alignTo(StackArgSize, *StackAlign);
4431 "secure entry function requires arguments on stack", dl.
getDebugLoc()));
4440 return CFP->getValueAPF().isPosZero();
4443 if (
Op.getOperand(1).getOpcode() == ARMISD::Wrapper) {
4444 SDValue WrapperOp =
Op.getOperand(1).getOperand(0);
4447 return CFP->getValueAPF().isPosZero();
4450 Op->getValueType(0) == MVT::f64) {
4454 if (BitcastOp->
getOpcode() == ARMISD::VMOVIMM &&
4465 const SDLoc &dl)
const {
4467 unsigned C = RHSC->getZExtValue();
4531 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::AND &&
4535 unsigned Mask =
LHS.getConstantOperandVal(1);
4537 uint64_t RHSV = RHSC->getZExtValue();
4538 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4540 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4554 if (Subtarget->isThumb1Only() &&
LHS->getOpcode() ==
ISD::SHL &&
4557 LHS.getConstantOperandVal(1) < 31) {
4558 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4583 unsigned CompareType;
4586 CompareType = ARMISD::CMP;
4591 CompareType = ARMISD::CMPZ;
4601 bool Signaling)
const {
4602 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4608 Flags = DAG.
getNode(Signaling ? ARMISD::CMPFPEw0 : ARMISD::CMPFPw0, dl,
4617std::pair<SDValue, SDValue>
4620 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
4632 switch (
Op.getOpcode()) {
4684 return std::make_pair(
Value, OverflowCmp);
4720 EVT VT =
Op.getValueType();
4721 SDVTList VTs = DAG.
getVTList(VT, MVT::i32);
4724 switch (
Op.getOpcode()) {
4742 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
4748 DAG.
getNode(ARMISD::CMOV, dl, MVT::i32,
4751 ARMcc, OverflowCmp);
4761 EVT VT =
Op.getValueType();
4762 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
4772 switch (
Op->getOpcode()) {
4774 NewOpcode = ARMISD::UQADD8b;
4777 NewOpcode = ARMISD::QADD8b;
4780 NewOpcode = ARMISD::UQSUB8b;
4783 NewOpcode = ARMISD::QSUB8b;
4788 switch (
Op->getOpcode()) {
4790 NewOpcode = ARMISD::UQADD16b;
4793 NewOpcode = ARMISD::QADD16b;
4796 NewOpcode = ARMISD::UQSUB16b;
4799 NewOpcode = ARMISD::QSUB16b;
4807 DAG.
getNode(NewOpcode, dl, MVT::i32,
4818 unsigned Opc =
Cond.getOpcode();
4820 if (
Cond.getResNo() == 1 &&
4828 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
4829 EVT VT =
Op.getValueType();
4831 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, OverflowCmp, DAG);
4839 if (
Cond.getOpcode() == ARMISD::CMOV &&
Cond.hasOneUse()) {
4840 const ConstantSDNode *CMOVTrue =
4842 const ConstantSDNode *CMOVFalse =
4845 if (CMOVTrue && CMOVFalse) {
4851 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
4853 False = SelectFalse;
4854 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
4860 return getCMOV(dl,
Op.getValueType(), True, False,
Cond.getOperand(2),
4861 Cond.getOperand(3), DAG);
4876 bool &swpCmpOps,
bool &swpVselOps) {
4904 swpCmpOps = !swpCmpOps;
4905 swpVselOps = !swpVselOps;
4928 if (!Subtarget->hasFP64() && VT == MVT::f64) {
4930 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
4932 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
4946 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, Flags);
4967 ((K ==
LHS && K == TrueVal) || (K ==
RHS && K == FalseVal))) ||
4969 ((K ==
RHS && K == TrueVal) || (K ==
LHS && K == FalseVal)));
4990 EVT VT =
Op.getValueType();
5012 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5025 int64_t PosVal = std::max(Val1, Val2);
5026 int64_t NegVal = std::min(Val1, Val2);
5038 return DAG.
getNode(ARMISD::SSAT, dl, VT, V2Tmp,
5041 return DAG.
getNode(ARMISD::USAT, dl, VT, V2Tmp,
5073 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5078 if (*K != KTmp || V != VTmp)
5089bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5091 return !Subtarget->hasVFP2Base();
5093 return !Subtarget->hasFP64();
5095 return !Subtarget->hasFullFP16();
5103 if (!CFVal || !CTVal || !Subtarget->hasV8_1MMainlineOps())
5111 if (TVal == ~FVal) {
5112 Opcode = ARMISD::CSINV;
5113 }
else if (TVal == ~FVal + 1) {
5114 Opcode = ARMISD::CSNEG;
5115 }
else if (TVal + 1 == FVal) {
5116 Opcode = ARMISD::CSINC;
5117 }
else if (TVal == FVal + 1) {
5118 Opcode = ARMISD::CSINC;
5121 InvertCond = !InvertCond;
5128 if (Opcode != ARMISD::CSINC &&
5132 InvertCond = !InvertCond;
5138 if (FVal == 0 && Opcode != ARMISD::CSINC) {
5141 InvertCond = !InvertCond;
5148 EVT VT =
Op.getValueType();
5152 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->isThumb2())
5164 if (VT == MVT::i32 &&
5183 if (
Op.getValueType().isInteger()) {
5191 LHS.getValueType() ==
RHS.getValueType()) {
5192 EVT VT =
LHS.getValueType();
5198 Shift = DAG.
getNOT(dl, Shift, VT);
5210 if (
LHS.getValueType() == MVT::i32) {
5214 matchCSET(Opcode, InvertCond, TrueVal, FalseVal, Subtarget)) {
5220 EVT VT =
Op.getValueType();
5221 return DAG.
getNode(Opcode, dl, VT,
Op,
Op, ARMcc, Cmp);
5225 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5230 if (!
RHS.getNode()) {
5236 if (
LHS.getValueType() == MVT::i32) {
5247 if (Subtarget->hasFPARMv8Base() && (
TrueVal.getValueType() == MVT::f16 ||
5248 TrueVal.getValueType() == MVT::f32 ||
5249 TrueVal.getValueType() == MVT::f64)) {
5263 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5273 if (Subtarget->hasFPARMv8Base() &&
5275 (
TrueVal.getValueType() == MVT::f16 ||
5276 TrueVal.getValueType() == MVT::f32 ||
5277 TrueVal.getValueType() == MVT::f64)) {
5278 bool swpCmpOps =
false;
5279 bool swpVselOps =
false;
5293 SDValue Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5296 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, Cmp, DAG);
5306 if (!
N->hasOneUse())
5309 if (!
N->getNumValues())
5311 EVT VT =
Op.getValueType();
5312 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5329 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5330 Ld->getPointerInfo(), Ld->getAlign(),
5331 Ld->getMemOperand()->getFlags());
5347 SDValue Ptr = Ld->getBasePtr();
5349 DAG.
getLoad(MVT::i32, dl, Ld->getChain(), Ptr, Ld->getPointerInfo(),
5350 Ld->getAlign(), Ld->getMemOperand()->
getFlags());
5355 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5356 Ld->getPointerInfo().getWithOffset(4),
5358 Ld->getMemOperand()->getFlags());
5376 bool LHSSeenZero =
false;
5378 bool RHSSeenZero =
false;
5380 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5391 if (
LHS.getValueType() == MVT::f32) {
5397 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5409 SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5410 return DAG.
getNode(ARMISD::BCC_i64, dl, MVT::Other,
Ops);
5425 return DAG.
getNode(ARMISD::CMOV,
DL, MVT::i32,
Op.getOperand(0), Neg,
5444 unsigned Opc =
Cond.getOpcode();
5446 !Subtarget->isThumb1Only();
5447 if (
Cond.getResNo() == 1 &&
5457 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5462 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5477 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5482 if (!
RHS.getNode()) {
5490 unsigned Opc =
LHS.getOpcode();
5492 !Subtarget->isThumb1Only();
5504 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5511 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc,
5515 if (
LHS.getValueType() == MVT::i32) {
5518 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, Dest, ARMcc, Cmp);
5521 SDNodeFlags
Flags =
Op->getFlags();
5522 if (
Flags.hasNoNaNs() &&
5527 if (
SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5541 Res = DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other,
Ops);
5555 Table = DAG.
getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI);
5558 if (Subtarget->isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5563 return DAG.
getNode(ARMISD::BR2_JT, dl, MVT::Other, Chain,
5564 Addr,
Op.getOperand(2), JTI);
5568 DAG.
getLoad((EVT)MVT::i32, dl, Chain, Addr,
5572 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5575 DAG.
getLoad(PTy, dl, Chain, Addr,
5578 return DAG.
getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI);
5583 EVT VT =
Op.getValueType();
5586 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5587 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5595 const EVT OpTy =
Op.getOperand(0).getValueType();
5596 if (OpTy == MVT::v4f32)
5598 else if (OpTy == MVT::v4f16 && HasFullFP16)
5600 else if (OpTy == MVT::v8f16 && HasFullFP16)
5605 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5608 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5613 EVT VT =
Op.getValueType();
5617 bool IsStrict =
Op->isStrictFPOpcode();
5618 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5620 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5633 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5634 CallOptions, Loc, Chain);
5644 Loc,
Op.getValueType(), SrcVal);
5653 EVT VT =
Op.getValueType();
5655 EVT FromVT =
Op.getOperand(0).getValueType();
5657 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5659 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5660 Subtarget->hasFP64())
5662 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5663 Subtarget->hasFullFP16())
5665 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5666 Subtarget->hasMVEFloatOps())
5668 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5669 Subtarget->hasMVEFloatOps())
5672 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
5689 EVT VT =
Op.getValueType();
5692 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
5698 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
5699 Op.getOperand(0).getValueType() == MVT::v8i16) &&
5700 "Invalid type for custom lowering!");
5705 if (VT == MVT::v4f32)
5706 DestVecType = MVT::v4i32;
5707 else if (VT == MVT::v4f16 && HasFullFP16)
5708 DestVecType = MVT::v4i16;
5709 else if (VT == MVT::v8f16 && HasFullFP16)
5710 DestVecType = MVT::v8i16;
5716 switch (
Op.getOpcode()) {
5728 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
5733 EVT VT =
Op.getValueType();
5736 if (isUnsupportedFloatingType(VT)) {
5746 CallOptions, SDLoc(
Op)).first;
5757 EVT VT =
Op.getValueType();
5761 bool UseNEON = !InGPR && Subtarget->hasNEON();
5768 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
5775 if (SrcVT == MVT::f32) {
5778 Tmp1 = DAG.
getNode(ARMISD::VSHLIMM, dl, OpVT,
5781 }
else if (VT == MVT::f32)
5782 Tmp1 = DAG.
getNode(ARMISD::VSHRuIMM, dl, MVT::v1i64,
5797 if (VT == MVT::f32) {
5809 if (SrcVT == MVT::f64)
5818 if (VT == MVT::f32) {
5831 return DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi);
5839 EVT VT =
Op.getValueType();
5841 unsigned Depth =
Op.getConstantOperandVal(0);
5843 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
5847 MachinePointerInfo());
5856 const ARMBaseRegisterInfo &ARI =
5857 *
static_cast<const ARMBaseRegisterInfo*
>(RegInfo);
5862 EVT VT =
Op.getValueType();
5864 unsigned Depth =
Op.getConstantOperandVal(0);
5869 MachinePointerInfo());
5877 return StringSwitch<Register>(
RegName)
5878 .Case(
"sp", ARM::SP)
5889 assert(
N->getValueType(0) == MVT::i64
5890 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
5893 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
5933 const APInt &APIntIndex = Index->getAPIntValue();
5935 NewIndex *= APIntIndex;
5964 EVT SrcVT =
Op.getValueType();
5965 EVT DstVT =
N->getValueType(0);
5967 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
5968 (DstVT == MVT::f16 || DstVT == MVT::bf16))
5969 return MoveToHPR(SDLoc(
N), DAG, MVT::i32, DstVT.
getSimpleVT(),
5972 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
5973 (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
5974 if (Subtarget->hasFullFP16() && !Subtarget->hasBF16())
5981 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
5993 DAG.
getNode(ARMISD::VMOVDRR, dl, MVT::f64,
Lo,
Hi));
6001 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6003 DAG.
getNode(ARMISD::VREV64, dl, SrcVT,
Op));
6005 Cvt = DAG.
getNode(ARMISD::VMOVRRD, dl,
6025 SDValue Vmov = DAG.
getNode(ARMISD::VMOVIMM, dl, VmovVT, EncodedVal);
6034 EVT VT =
Op.getValueType();
6056 DAG.
getNode(ARMISD::CMOV, dl, VT, LoSmallShift, LoBigShift, ARMcc, CmpLo);
6066 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6077 EVT VT =
Op.getValueType();
6098 DAG.
getNode(ARMISD::CMOV, dl, VT, HiSmallShift, HiBigShift, ARMcc, CmpHi);
6119 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6171 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6199 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6229 EVT VT =
N->getValueType(0);
6230 if (VT.
isVector() && ST->hasNEON()) {
6239 if (ElemTy == MVT::i8) {
6247 if ((ElemTy == MVT::i16 || ElemTy == MVT::i32) &&
6250 unsigned NumBits = ElemTy.getSizeInBits();
6252 DAG.
getNode(ARMISD::VMOVIMM, dl, VT,
6262 if (ElemTy == MVT::i64) {
6275 if (!ST->hasV6T2Ops())
6284 EVT VT =
N->getValueType(0);
6287 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6288 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6289 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6290 "Unexpected type for custom ctpop lowering");
6298 unsigned EltSize = 8;
6321 Op =
Op.getOperand(0);
6323 APInt SplatBits, SplatUndef;
6324 unsigned SplatBitSize;
6327 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6329 SplatBitSize > ElementBits)
6340 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6344 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6355 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6360 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6361 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6370 EVT VT =
N->getValueType(0);
6385 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
6387 return DAG.
getNode(ARMISD::VSHLu, dl, VT,
N->getOperand(0),
6392 "unexpected vector shift opcode");
6394 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6395 unsigned VShiftOpc =
6396 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
6397 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6403 EVT ShiftVT =
N->getOperand(1).getValueType();
6406 unsigned VShiftOpc =
6407 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHLs : ARMISD::VSHLu);
6408 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6413 EVT VT =
N->getValueType(0);
6422 "Unknown shift to lower!");
6424 unsigned ShOpc =
N->getOpcode();
6425 if (ST->hasMVEIntegerOps()) {
6427 unsigned ShPartsOpc = ARMISD::LSLL;
6448 ShPartsOpc = ARMISD::LSRL;
6450 ShPartsOpc = ARMISD::ASRL;
6455 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6469 if (ST->isThumb1Only())
6474 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6478 unsigned Opc =
N->getOpcode() ==
ISD::SRL ? ARMISD::LSRS1 : ARMISD::ASRS1;
6482 Lo = DAG.
getNode(ARMISD::RRX, dl, MVT::i32,
Lo,
Hi.getValue(1));
6490 bool Invert =
false;
6497 EVT VT =
Op.getValueType();
6505 assert(ST->hasMVEIntegerOps() &&
6506 "No hardware support for integer vector comparison!");
6508 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6529 SDValue Reversed = DAG.
getNode(ARMISD::VREV64, dl, SplitVT, Cmp);
6533 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6543 switch (SetCCOpcode) {
6547 if (ST->hasMVEFloatOps()) {
6550 Invert =
true; [[fallthrough]];
6555 case ISD::SETLT: Swap =
true; [[fallthrough]];
6559 case ISD::SETLE: Swap =
true; [[fallthrough]];
6575 Result = DAG.
getNOT(dl, Result, VT);
6578 case ISD::SETUO: Invert =
true; [[fallthrough]];
6587 Result = DAG.
getNOT(dl, Result, VT);
6593 switch (SetCCOpcode) {
6596 if (ST->hasMVEIntegerOps()) {
6599 Invert =
true; [[fallthrough]];
6602 case ISD::SETLT: Swap =
true; [[fallthrough]];
6604 case ISD::SETLE: Swap =
true; [[fallthrough]];
6621 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::BITCAST)
6624 if (AndOp.getNode() && AndOp.getOpcode() ==
ISD::AND) {
6629 Result = DAG.
getNOT(dl, Result, VT);
6654 Result = DAG.
getNode(ARMISD::VCMPZ, dl, CmpVT, Op0,
6657 Result = DAG.
getNode(ARMISD::VCMP, dl, CmpVT, Op0, Op1,
6663 Result = DAG.
getNOT(dl, Result, VT);
6675 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
6691 return DAG.
getNode(ARMISD::CMOV,
DL,
Op.getValueType(), FVal, TVal, ARMcc,
6702 unsigned OpCmode, Imm;
6713 switch (SplatBitSize) {
6718 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
6721 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
6726 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
6727 if ((SplatBits & ~0xff) == 0) {
6733 if ((SplatBits & ~0xff00) == 0) {
6736 Imm = SplatBits >> 8;
6746 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
6747 if ((SplatBits & ~0xff) == 0) {
6753 if ((SplatBits & ~0xff00) == 0) {
6756 Imm = SplatBits >> 8;
6759 if ((SplatBits & ~0xff0000) == 0) {
6762 Imm = SplatBits >> 16;
6765 if ((SplatBits & ~0xff000000) == 0) {
6768 Imm = SplatBits >> 24;
6775 if ((SplatBits & ~0xffff) == 0 &&
6776 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
6779 Imm = SplatBits >> 8;
6787 if ((SplatBits & ~0xffffff) == 0 &&
6788 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
6791 Imm = SplatBits >> 16;
6807 unsigned ImmMask = 1;
6809 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
6810 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
6812 }
else if ((SplatBits & BitMask) != 0) {
6821 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
6835 EVT VT =
Op.getValueType();
6836 bool IsDouble = (VT == MVT::f64);
6842 if (
ST->genExecuteOnly()) {
6844 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
6845 "Unexpected architecture");
6863 return DAG.
getNode(ARMISD::VMOVSR,
DL, VT,
6868 if (!
ST->hasVFP3Base())
6873 if (IsDouble && !Subtarget->hasFP64())
6880 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
6898 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
6907 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
6961 unsigned ExpectedElt = Imm;
6962 for (
unsigned i = 1; i < NumElts; ++i) {
6966 if (ExpectedElt == NumElts)
6969 if (M[i] < 0)
continue;
6970 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
6978 bool &ReverseVEXT,
unsigned &Imm) {
6980 ReverseVEXT =
false;
6991 unsigned ExpectedElt = Imm;
6992 for (
unsigned i = 1; i < NumElts; ++i) {
6996 if (ExpectedElt == NumElts * 2) {
7001 if (M[i] < 0)
continue;
7002 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7017 return VT == MVT::v8i8 && M.size() == 8;
7022 if (Mask.size() == Elements * 2)
7023 return Index / Elements;
7024 return Mask[Index] == 0 ? 0 : 1;
7054 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7062 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7064 for (
unsigned j = 0; j < NumElts; j += 2) {
7065 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7066 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + NumElts + WhichResult))
7071 if (M.size() == NumElts*2)
7086 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7089 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7091 for (
unsigned j = 0; j < NumElts; j += 2) {
7092 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7093 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + WhichResult))
7098 if (M.size() == NumElts*2)
7118 if (M.size() != NumElts && M.size() != NumElts*2)
7121 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7123 for (
unsigned j = 0; j < NumElts; ++j) {
7124 if (M[i+j] >= 0 && (
unsigned) M[i+j] != 2 * j + WhichResult)
7129 if (M.size() == NumElts*2)
7148 if (M.size() != NumElts && M.size() != NumElts*2)
7151 unsigned Half = NumElts / 2;
7152 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7154 for (
unsigned j = 0; j < NumElts; j += Half) {
7155 unsigned Idx = WhichResult;
7156 for (
unsigned k = 0; k < Half; ++k) {
7157 int MIdx = M[i + j + k];
7158 if (MIdx >= 0 && (
unsigned) MIdx != Idx)
7165 if (M.size() == NumElts*2)
7189 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7192 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7194 unsigned Idx = WhichResult * NumElts / 2;
7195 for (
unsigned j = 0; j < NumElts; j += 2) {
7196 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7197 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx + NumElts))
7203 if (M.size() == NumElts*2)
7222 if ((M.size() != NumElts && M.size() != NumElts * 2) || NumElts % 2 != 0)
7225 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7227 unsigned Idx = WhichResult * NumElts / 2;
7228 for (
unsigned j = 0; j < NumElts; j += 2) {
7229 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != Idx) ||
7230 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != Idx))
7236 if (M.size() == NumElts*2)
7249 unsigned &WhichResult,
7252 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7253 return ARMISD::VTRN;
7254 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7255 return ARMISD::VUZP;
7256 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7257 return ARMISD::VZIP;
7261 return ARMISD::VTRN;
7263 return ARMISD::VUZP;
7265 return ARMISD::VZIP;
7274 if (NumElts != M.size())
7278 for (
unsigned i = 0; i != NumElts; ++i)
7279 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7288 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7296 int Ofs = Top ? 1 : 0;
7297 int Upper = SingleSource ? 0 : NumElts;
7298 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7299 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7301 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7310 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7319 unsigned Offset = Top ? 0 : 1;
7320 unsigned N = SingleSource ? 0 : NumElts;
7321 for (
unsigned i = 0; i < NumElts; i += 2) {
7322 if (M[i] >= 0 && M[i] != (
int)i)
7324 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7333 if (NumElts != M.size())
7341 unsigned Off0 = rev ? NumElts / 2 : 0;
7342 unsigned Off1 = rev ? 0 : NumElts / 2;
7343 for (
unsigned i = 0; i < NumElts; i += 2) {
7344 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7346 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7362 if (!ST->hasMVEFloatOps())
7367 if (VT != MVT::v8f16)
7388 for (
unsigned i = 1; i < 4; i++) {
7403 return DAG.
getNode(ARMISD::VCVTN, dl, VT, N1, Op1,
7415 if (!ST->hasMVEFloatOps())
7420 if (VT != MVT::v4f32)
7436 for (
unsigned i = 1; i < 4; i++) {
7447 return DAG.
getNode(ARMISD::VCVTL, dl, VT, Op0,
7459 Val =
N->getAsZExtVal();
7461 if (ST->isThumb1Only()) {
7462 if (Val <= 255 || ~Val <= 255)
7474 EVT VT =
Op.getValueType();
7476 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7480 unsigned BitsPerBool;
7484 }
else if (NumElts == 4) {
7487 }
else if (NumElts == 8) {
7490 }
else if (NumElts == 16) {
7501 return U.get().isUndef() || U.get() == FirstOp;
7505 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), Ext);
7509 unsigned Bits32 = 0;
7510 for (
unsigned i = 0; i < NumElts; ++i) {
7514 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7516 Bits32 |= BoolMask << (i * BitsPerBool);
7522 for (
unsigned i = 0; i < NumElts; ++i) {
7535 if (!ST->hasMVEIntegerOps())
7539 EVT VT =
Op.getValueType();
7549 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7553 for (
unsigned I = 2;
I < NumElts;
I++) {
7569 switch (
N->getOpcode()) {
7580 return N->getOperand(1).getNode() ==
Op;
7582 switch (
N->getConstantOperandVal(0)) {
7583 case Intrinsic::arm_mve_add_predicated:
7584 case Intrinsic::arm_mve_mul_predicated:
7585 case Intrinsic::arm_mve_qadd_predicated:
7586 case Intrinsic::arm_mve_vhadd:
7587 case Intrinsic::arm_mve_hadd_predicated:
7588 case Intrinsic::arm_mve_vqdmulh:
7589 case Intrinsic::arm_mve_qdmulh_predicated:
7590 case Intrinsic::arm_mve_vqrdmulh:
7591 case Intrinsic::arm_mve_qrdmulh_predicated:
7592 case Intrinsic::arm_mve_vqdmull:
7593 case Intrinsic::arm_mve_vqdmull_predicated:
7595 case Intrinsic::arm_mve_sub_predicated:
7596 case Intrinsic::arm_mve_qsub_predicated:
7597 case Intrinsic::arm_mve_vhsub:
7598 case Intrinsic::arm_mve_hsub_predicated:
7599 return N->getOperand(2).getNode() ==
Op;
7614 EVT VT =
Op.getValueType();
7622 APInt SplatBits, SplatUndef;
7623 unsigned SplatBitSize;
7625 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7632 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7634 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7635 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7636 : SplatBitSize == 16 ? MVT::v8i16
7640 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7643 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7644 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7649 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7653 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7657 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7659 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
7663 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vmov);
7667 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
7671 return DAG.
getNode(ARMISD::VMOVFPIMM, dl, VT, Val);
7677 if (
ST->hasMVEIntegerOps() &&
7678 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
7679 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7680 : SplatBitSize == 16 ? MVT::v8i16
7684 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, VDup);
7697 bool isOnlyLowElement =
true;
7698 bool usesOnlyOneValue =
true;
7699 bool hasDominantValue =
false;
7704 DenseMap<SDValue, unsigned> ValueCounts;
7706 for (
unsigned i = 0; i < NumElts; ++i) {
7711 isOnlyLowElement =
false;
7715 unsigned &
Count = ValueCounts[
V];
7718 if (++
Count > (NumElts / 2)) {
7719 hasDominantValue =
true;
7723 if (ValueCounts.
size() != 1)
7724 usesOnlyOneValue =
false;
7725 if (!
Value.getNode() && !ValueCounts.
empty())
7728 if (ValueCounts.
empty())
7740 if (hasDominantValue && EltSize <= 32) {
7749 ConstantSDNode *constIndex;
7756 if (VT !=
Value->getOperand(0).getValueType()) {
7759 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7764 N = DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
7769 if (!usesOnlyOneValue) {
7772 for (
unsigned I = 0;
I < NumElts; ++
I) {
7777 Ops.push_back(
Op.getOperand(
I));
7787 assert(FVT == MVT::f32 || FVT == MVT::f16);
7788 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
7789 for (
unsigned i = 0; i < NumElts; ++i)
7794 Val = LowerBUILD_VECTOR(Val, DAG, ST);
7798 if (usesOnlyOneValue) {
7801 return DAG.
getNode(ARMISD::VDUP, dl, VT, Val);
7825 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
7845 if (EltSize >= 32) {
7851 for (
unsigned i = 0; i < NumElts; ++i)
7865 for (
unsigned i = 0 ; i < NumElts; ++i) {
7884 EVT VT =
Op.getValueType();
7887 struct ShuffleSourceInfo {
7889 unsigned MinElt = std::numeric_limits<unsigned>::max();
7890 unsigned MaxElt = 0;
7900 int WindowScale = 1;
7902 ShuffleSourceInfo(
SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
7910 for (
unsigned i = 0; i < NumElts; ++i) {
7925 SDValue SourceVec =
V.getOperand(0);
7927 if (Source == Sources.
end())
7931 unsigned EltNo =
V.getConstantOperandVal(1);
7938 if (Sources.
size() > 2)
7944 for (
auto &Source : Sources) {
7945 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
7946 if (SrcEltTy.
bitsLT(SmallestEltTy))
7947 SmallestEltTy = SrcEltTy;
7949 unsigned ResMultiplier =
7957 for (
auto &Src : Sources) {
7958 EVT SrcVT = Src.ShuffleVec.getValueType();
7962 if (SrcVTSize == VTSize)
7971 if (SrcVTSize < VTSize) {
7972 if (2 * SrcVTSize != VTSize)
7978 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
7982 if (SrcVTSize != 2 * VTSize)
7985 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
7990 if (Src.MinElt >= NumSrcElts) {
7995 Src.WindowBase = -NumSrcElts;
7996 }
else if (Src.MaxElt < NumSrcElts) {
8010 Src.ShuffleVec = DAG.
getNode(ARMISD::VEXT, dl, DestVT, VEXTSrc1,
8013 Src.WindowBase = -Src.MinElt;
8020 for (
auto &Src : Sources) {
8021 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
8022 if (SrcEltTy == SmallestEltTy)
8025 Src.ShuffleVec = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, ShuffleVT, Src.ShuffleVec);
8027 Src.WindowBase *= Src.WindowScale;
8032 for (
auto Src : Sources)
8033 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
8041 if (
Entry.isUndef())
8050 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
8053 int LanesDefined = BitsDefined / BitsPerShuffleLane;
8057 int *LaneMask = &
Mask[i * ResMultiplier];
8059 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
8060 ExtractBase += NumElts * (Src - Sources.begin());
8061 for (
int j = 0;
j < LanesDefined; ++
j)
8062 LaneMask[j] = ExtractBase + j;
8068 assert(Sources.size() <= 2 &&
"Too many sources!");
8071 for (
unsigned i = 0; i < Sources.size(); ++i)
8078 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Shuffle);
8100 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8120 unsigned PFIndexes[4];
8121 for (
unsigned i = 0; i != 4; ++i) {
8125 PFIndexes[i] = M[i];
8129 unsigned PFTableIndex =
8130 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8132 unsigned Cost = (PFEntry >> 30);
8138 bool ReverseVEXT, isV_UNDEF;
8139 unsigned Imm, WhichResult;
8142 if (EltSize >= 32 ||
8149 else if (Subtarget->hasNEON() &&
8154 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8157 else if (Subtarget->hasMVEIntegerOps() &&
8161 else if (Subtarget->hasMVEIntegerOps() &&
8175 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8176 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8177 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8180 if (LHSID == (1*9+2)*9+3)
return LHS;
8181 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8195 return DAG.
getNode(ARMISD::VREV64, dl, VT, OpLHS);
8198 return DAG.
getNode(ARMISD::VREV32, dl, VT, OpLHS);
8201 return DAG.
getNode(ARMISD::VREV16, dl, VT, OpLHS);
8206 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT,
8211 return DAG.
getNode(ARMISD::VEXT, dl, VT,
8238 for (
int I : ShuffleMask)
8242 return DAG.
getNode(ARMISD::VTBL1,
DL, MVT::v8i8, V1,
8245 return DAG.
getNode(ARMISD::VTBL2,
DL, MVT::v8i8, V1, V2,
8251 EVT VT =
Op.getValueType();
8253 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8254 "Expect an v8i16/v16i8 type");
8260 std::vector<int> NewMask;
8264 NewMask.push_back(i);
8294 AllZeroes = DAG.
getNode(ARMISD::VMOVIMM, dl, MVT::v16i8, AllZeroes);
8304 if (VT != MVT::v16i1)
8305 RecastV1 = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Pred);
8320 EVT VT =
Op.getValueType();
8324 assert(ST->hasMVEIntegerOps() &&
8325 "No support for vector shuffle of boolean predicates");
8335 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT, srl);
8351 "Expected identical vector type in expanded i1 shuffle!");
8355 PredAsVector2, ShuffleMask);
8360 if (VT == MVT::v2i1) {
8361 SDValue BC = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Shuffled);
8364 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
8366 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Shuffled,
8377 EVT VT =
Op.getValueType();
8381 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8382 "Unexpected vector type");
8384 int QuarterSize = NumElts / 4;
8393 for (
int i = 0; i <
Length; i++) {
8394 if (ShuffleMask[Start + i] >= 0) {
8395 if (ShuffleMask[Start + i] %
Length != i)
8397 MovIdx = ShuffleMask[Start + i] /
Length;
8405 for (
int i = 1; i <
Length; i++) {
8406 if (ShuffleMask[Start + i] >= 0 &&
8407 (ShuffleMask[Start + i] /
Length != MovIdx ||
8408 ShuffleMask[Start + i] %
Length != i))
8414 for (
int Part = 0; Part < 4; ++Part) {
8416 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8430 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8435 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8437 for (
int Part = 0; Part < 4; ++Part)
8438 for (
int i = 0; i < QuarterSize; i++)
8440 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8442 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8445 for (
int Part = 0; Part < 4; ++Part)
8461 EVT VT =
Op.getValueType();
8473 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8477 if (Mask[i] != i + BaseOffset) {
8478 if (OffElement == -1)
8484 return NonUndef > 2 && OffElement != -1;
8488 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8490 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8501 ShuffleMask[OffElement] < (
int)NumElts ? V1 : V2,
8512 EVT VT =
Op.getValueType();
8516 if (ST->hasMVEIntegerOps() && EltSize == 1)
8527 if (EltSize <= 32) {
8531 if (Lane == -1) Lane = 0;
8542 bool IsScalarToVector =
true;
8545 IsScalarToVector =
false;
8548 if (IsScalarToVector)
8551 return DAG.
getNode(ARMISD::VDUPLANE, dl, VT, V1,
8555 bool ReverseVEXT =
false;
8557 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) {
8560 return DAG.
getNode(ARMISD::VEXT, dl, VT, V1, V2,
8565 return DAG.
getNode(ARMISD::VREV64, dl, VT, V1);
8567 return DAG.
getNode(ARMISD::VREV32, dl, VT, V1);
8569 return DAG.
getNode(ARMISD::VREV16, dl, VT, V1);
8572 return DAG.
getNode(ARMISD::VEXT, dl, VT, V1, V1,
8581 unsigned WhichResult = 0;
8582 bool isV_UNDEF =
false;
8583 if (ST->hasNEON()) {
8585 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8592 if (ST->hasMVEIntegerOps()) {
8594 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V2, V1,
8597 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V1, V2,
8600 return DAG.
getNode(ARMISD::VMOVN, dl, VT, V1, V1,
8627 }) &&
"Unexpected shuffle index into UNDEF operand!");
8630 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8633 assert((WhichResult == 0) &&
8634 "In-place shuffle of concat can only have one result!");
8643 if (ST->hasMVEIntegerOps() && EltSize <= 32) {
8647 for (
bool Top : {
false,
true}) {
8648 for (
bool SingleSource : {
false,
true}) {
8649 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8654 SingleSource ? V1 : V2);
8670 unsigned PFIndexes[4];
8671 for (
unsigned i = 0; i != 4; ++i) {
8672 if (ShuffleMask[i] < 0)
8675 PFIndexes[i] = ShuffleMask[i];
8679 unsigned PFTableIndex =
8680 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8682 unsigned Cost = (PFEntry >> 30);
8688 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8689 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8699 if (EltSize >= 32) {
8707 for (
unsigned i = 0; i < NumElts; ++i) {
8708 if (ShuffleMask[i] < 0)
8712 ShuffleMask[i] < (
int)NumElts ? V1 : V2,
8720 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8724 if (ST->hasNEON() && VT == MVT::v8i8)
8728 if (ST->hasMVEIntegerOps())
8737 EVT VecVT =
Op.getOperand(0).getValueType();
8740 assert(ST->hasMVEIntegerOps() &&
8741 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8744 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8745 unsigned Lane =
Op.getConstantOperandVal(2);
8746 unsigned LaneWidth =
8748 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
8753 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl,
Op.getValueType(), BFI);
8766 if (Subtarget->hasMVEIntegerOps() &&
8767 Op.getValueType().getScalarSizeInBits() == 1)
8791 IVecIn, IElt, Lane);
8800 EVT VecVT =
Op.getOperand(0).getValueType();
8803 assert(ST->hasMVEIntegerOps() &&
8804 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
8807 DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32,
Op->getOperand(0));
8808 unsigned Lane =
Op.getConstantOperandVal(1);
8809 unsigned LaneWidth =
8831 return DAG.
getNode(ARMISD::VGETLANEu, dl, MVT::i32, Vec, Lane);
8840 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
8841 "Unexpected custom CONCAT_VECTORS lowering");
8843 "Unexpected custom CONCAT_VECTORS lowering");
8844 assert(ST->hasMVEIntegerOps() &&
8845 "CONCAT_VECTORS lowering only supported for MVE");
8849 EVT Op2VT = V2.getValueType();
8850 assert(Op1VT == Op2VT &&
"Operand types don't match!");
8851 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
8852 "Unexpected i1 concat operations!");
8865 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
8870 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
8879 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
8880 EVT NewVT = NewV.getValueType();
8881 EVT ConcatVT = ConVec.getValueType();
8882 unsigned ExtScale = 1;
8883 if (NewVT == MVT::v2f64) {
8884 NewV = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, NewV);
8897 ConVec = ExtractInto(NewV1, ConVec, j);
8898 ConVec = ExtractInto(NewV2, ConVec, j);
8902 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, ConVec,
8908 while (ConcatOps.
size() > 1) {
8909 for (
unsigned I = 0,
E = ConcatOps.
size();
I !=
E;
I += 2) {
8912 ConcatOps[
I / 2] = ConcatPair(V1, V2);
8916 return ConcatOps[0];
8921 EVT VT =
Op->getValueType(0);
8927 assert(
Op.getValueType().is128BitVector() &&
Op.getNumOperands() == 2 &&
8928 "unexpected CONCAT_VECTORS");
8949 EVT VT =
Op.getValueType();
8955 "Unexpected custom EXTRACT_SUBVECTOR lowering");
8956 assert(ST->hasMVEIntegerOps() &&
8957 "EXTRACT_SUBVECTOR lowering only supported for MVE");
8967 EVT SubVT = MVT::v4i32;
8969 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j += 2) {
8979 return DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v2i1, Cmp);
8984 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j++) {
8993 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, SubVec,
9000 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
9001 EVT VT =
N->getValueType(0);
9002 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
9003 "Expected a vector i1 type!");
9005 EVT FromVT =
Op.getValueType();
9016 if (!Subtarget->hasMVEIntegerOps())
9019 EVT ToVT =
N->getValueType(0);
9062 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
9064 EVT FromVT =
N->getOperand(0).getValueType();
9065 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9076 if (!Subtarget->hasMVEIntegerOps())
9081 EVT ToVT =
N->getValueType(0);
9082 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9085 EVT FromVT =
Op.getValueType();
9086 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9100 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9101 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9113 EVT VT =
N->getValueType(0);
9115 SDNode *BVN =
N->getOperand(0).getNode();
9120 unsigned HiElt = 1 - LoElt;
9125 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9141 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9142 SDNode *Elt =
N->getOperand(i).getNode();
9145 unsigned HalfSize = EltSize / 2;
9147 if (!
isIntN(HalfSize,
C->getSExtValue()))
9150 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9189 switch (OrigSimpleTy) {
9205 unsigned ExtOpcode) {
9228 if (ExtendedTy == LD->getMemoryVT())
9229 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9230 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9231 LD->getMemOperand()->getFlags());
9237 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9238 LD->getMemoryVT(), LD->getAlign(),
9239 LD->getMemOperand()->getFlags());
9252 N->getOperand(0)->getValueType(0),
9258 "Expected extending load");
9264 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9273 SDNode *BVN =
N->getOperand(0).getNode();
9275 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9283 EVT VT =
N->getValueType(0);
9289 for (
unsigned i = 0; i != NumElts; ++i) {
9290 const APInt &CInt =
N->getConstantOperandAPInt(i);
9299 unsigned Opcode =
N->getOpcode();
9301 SDNode *N0 =
N->getOperand(0).getNode();
9302 SDNode *N1 =
N->getOperand(1).getNode();
9310 unsigned Opcode =
N->getOpcode();
9312 SDNode *N0 =
N->getOperand(0).getNode();
9313 SDNode *N1 =
N->getOperand(1).getNode();
9323 EVT VT =
Op.getValueType();
9325 "unexpected type for custom-lowering ISD::MUL");
9326 SDNode *N0 =
Op.getOperand(0).getNode();
9327 SDNode *N1 =
Op.getOperand(1).getNode();
9328 unsigned NewOpc = 0;
9332 if (isN0SExt && isN1SExt)
9333 NewOpc = ARMISD::VMULLs;
9337 if (isN0ZExt && isN1ZExt)
9338 NewOpc = ARMISD::VMULLu;
9339 else if (isN1SExt || isN1ZExt) {
9343 NewOpc = ARMISD::VMULLs;
9346 NewOpc = ARMISD::VMULLu;
9350 NewOpc = ARMISD::VMULLu;
9356 if (VT == MVT::v2i64)
9373 "unexpected types for extended operands to VMULL");
9374 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9409 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9443 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9446 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9467 EVT VT =
Op.getValueType();
9468 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9469 "unexpected type for custom-lowering ISD::SDIV");
9476 if (VT == MVT::v8i8) {
9504 EVT VT =
Op.getValueType();
9505 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9506 "unexpected type for custom-lowering ISD::UDIV");
9513 if (VT == MVT::v8i8) {
9552 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9555 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9559 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9580 EVT VT =
N->getValueType(0);
9593 Result = DAG.
getNode(ARMISD::ADDE,
DL, VTs,
Op.getOperand(0),
9594 Op.getOperand(1), Carry);
9607 Result = DAG.
getNode(ARMISD::SUBE,
DL, VTs,
Op.getOperand(0),
9608 Op.getOperand(1), Carry);
9625 EVT VT =
Op.getValueType();
9626 assert((VT == MVT::i32 || VT == MVT::i64) &&
9627 "unexpected type for custom lowering DIV");
9633 LC = VT == MVT::i32 ? RTLIB::SDIVREM_I32 : RTLIB::SDIVREM_I64;
9635 LC = VT == MVT::i32 ? RTLIB::UDIVREM_I32 : RTLIB::UDIVREM_I64;
9642 for (
auto AI : {1, 0}) {
9644 Args.emplace_back(Operand,
9661ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
9669 const bool MinSize =
ST.hasMinSize();
9670 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
9671 :
ST.hasDivideInARMMode();
9675 if (
N->getOperand(0).getValueType().isVector())
9680 if (!(MinSize && HasDivide))
9693 if (Divisor.
sgt(128))
9701 assert(
Op.getValueType() == MVT::i32 &&
9702 "unexpected type for custom lowering DIV");
9705 SDValue DBZCHK = DAG.
getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other,
9708 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
9714 if (
N->getValueType(0) == MVT::i32)
9715 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
Op);
9718 return DAG.
getNode(ARMISD::WIN__DBZCHK,
DL, MVT::Other, InChain,
9722void ARMTargetLowering::ExpandDIV_Windows(
9727 assert(
Op.getValueType() == MVT::i64 &&
9728 "unexpected type for custom lowering DIV");
9743std::pair<SDValue, SDValue>
9744ARMTargetLowering::LowerAEABIUnalignedLoad(
SDValue Op,
9750 EVT MemVT =
LD->getMemoryVT();
9751 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9755 unsigned AS =
LD->getAddressSpace();
9756 Align Alignment =
LD->getAlign();
9758 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9761 Alignment <= llvm::Align(2)) {
9764 (MemVT == MVT::i32) ? RTLIB::AEABI_UREAD4 : RTLIB::AEABI_UREAD8;
9770 Opts, dl,
LD->getChain());
9795 EVT MemVT =
ST->getMemoryVT();
9796 if (MemVT != MVT::i32 && MemVT != MVT::i64)
9800 unsigned AS =
ST->getAddressSpace();
9801 Align Alignment =
ST->getAlign();
9803 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
9806 Alignment <= llvm::Align(2)) {
9812 if (
ST->isTruncatingStore())
9816 (MemVT == MVT::i32) ? RTLIB::AEABI_UWRITE4 : RTLIB::AEABI_UWRITE8;
9820 makeLibCall(DAG, LC, MVT::isVoid, {StoreVal,
ST->getBasePtr()}, Opts,
9821 dl,
ST->getChain());
9823 return CallResult.second;
9834 EVT MemVT = LD->getMemoryVT();
9835 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9836 MemVT == MVT::v16i1) &&
9837 "Expected a predicate type!");
9838 assert(MemVT ==
Op.getValueType());
9840 "Expected a non-extending load");
9841 assert(LD->isUnindexed() &&
"Expected a unindexed load");
9855 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
9857 LD->getMemOperand());
9863 SDValue Pred = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::v16i1, Val);
9864 if (MemVT != MVT::v16i1)
9873 EVT MemVT =
LD->getMemoryVT();
9875 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
9876 !Subtarget->isThumb1Only() &&
LD->isVolatile() &&
9877 LD->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
9878 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
9881 ARMISD::LDRD, dl, DAG.
getVTList({MVT::i32, MVT::i32, MVT::Other}),
9882 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
9887 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
9888 auto Pair = LowerAEABIUnalignedLoad(
SDValue(
N, 0), DAG);
9890 Results.push_back(Pair.first);
9891 Results.push_back(Pair.second);
9898 EVT MemVT = ST->getMemoryVT();
9899 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9900 MemVT == MVT::v16i1) &&
9901 "Expected a predicate type!");
9902 assert(MemVT == ST->getValue().getValueType());
9903 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
9904 assert(ST->isUnindexed() &&
"Expected a unindexed store");
9909 SDValue Build = ST->getValue();
9910 if (MemVT != MVT::v16i1) {
9923 SDValue GRP = DAG.
getNode(ARMISD::PREDICATE_CAST, dl, MVT::i32, Build);
9929 ST->getChain(), dl, GRP, ST->getBasePtr(),
9931 ST->getMemOperand());
9937 EVT MemVT =
ST->getMemoryVT();
9939 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
9940 !Subtarget->isThumb1Only() &&
ST->isVolatile() &&
9941 ST->getAlign() >= Subtarget->getDualLoadStoreAlignment()) {
9942 assert(
ST->isUnindexed() &&
"Stores should be unindexed at this point.");
9943 SDNode *
N =
Op.getNode();
9956 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
9957 MemVT,
ST->getMemOperand());
9958 }
else if (Subtarget->hasMVEIntegerOps() &&
9959 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
9960 MemVT == MVT::v16i1))) {
9962 }
else if (MemVT == MVT::i32 || MemVT == MVT::i64) {
9963 return LowerAEABIUnalignedStore(
Op, DAG);
9970 (
N->getOpcode() == ARMISD::VMOVIMM &&
9976 MVT VT =
Op.getSimpleValueType();
9978 SDValue PassThru =
N->getPassThru();
9989 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
9990 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
9991 N->getExtensionType(),
N->isExpandingLoad());
9994 PassThru.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
9996 if (!PassThru.
isUndef() && !PassThruIsCastZero)
10003 if (!ST->hasMVEIntegerOps())
10007 unsigned BaseOpcode = 0;
10008 switch (
Op->getOpcode()) {
10024 unsigned NumActiveLanes = NumElts;
10026 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10027 NumActiveLanes == 2) &&
10028 "Only expected a power 2 vector size");
10032 while (NumActiveLanes > 4) {
10033 unsigned RevOpcode = NumActiveLanes == 16 ? ARMISD::VREV16 : ARMISD::VREV32;
10035 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
10036 NumActiveLanes /= 2;
10040 if (NumActiveLanes == 4) {
10050 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10051 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
10052 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
10058 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10062 if (EltVT !=
Op->getValueType(0))
10069 if (!ST->hasMVEFloatOps())
10076 if (!ST->hasNEON())
10084 unsigned PairwiseIntrinsic = 0;
10085 switch (
Op->getOpcode()) {
10089 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
10092 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
10095 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
10098 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
10104 unsigned NumActiveLanes = NumElts;
10106 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10107 NumActiveLanes == 2) &&
10108 "Only expected a power 2 vector size");
10114 VT =
Lo.getValueType();
10116 NumActiveLanes /= 2;
10120 while (NumActiveLanes > 1) {
10122 NumActiveLanes /= 2;
10129 if (EltVT !=
Op.getValueType()) {
10130 unsigned Extend = 0;
10131 switch (
Op->getOpcode()) {
10143 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10188 const SDValue Ops[] = {RegClass, V0, SubReg0, V1, SubReg1};
10194 SDLoc dl(V.getNode());
10195 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10205 assert(
N->getValueType(0) == MVT::i64 &&
10206 "AtomicCmpSwap on types less than 64 should be legal");
10215 ARM::CMP_SWAP_64,
SDLoc(
N),
10216 DAG.
getVTList(MVT::Untyped, MVT::Untyped, MVT::Other),
Ops);
10235 EVT VT =
Op.getValueType();
10244 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10246 Chain, IsSignaling);
10247 if (!
RHS.getNode()) {
10263 SDValue Result = getCMOV(dl, VT, False, True, ARMcc, Cmp, DAG);
10265 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10266 Result = getCMOV(dl, VT, Result, True, ARMcc, Cmp, DAG);
10283 MVT SVT =
Op.getOperand(0).getSimpleValueType();
10286 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
10299 if (!IsSigned && Subtarget->isThumb1Only()) {
10317 Sub1Result, Sub1Result, Flags1);
10332 if (
Op.getValueType() != MVT::i32)
10346 unsigned Opcode = ARMISD::SUBC;
10355 bool CanUseAdd =
false;
10371 Opcode = ARMISD::ADDC;
10395 SDValue Result1 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, OpResult, One,
10396 GTCondValue, Flags);
10400 SDValue Result2 = DAG.
getNode(ARMISD::CMOV, dl, MVT::i32, Result1, MinusOne,
10401 LTCondValue, Flags);
10403 if (
Op.getValueType() != MVT::i32)
10411 switch (
Op.getOpcode()) {
10443 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10447 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10448 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10470 return LowerSET_FPMODE(
Op, DAG);
10472 return LowerRESET_FPMODE(
Op, DAG);
10476 !
Op.getValueType().isVector())
10477 return LowerDIV_Windows(
Op, DAG,
true);
10481 !
Op.getValueType().isVector())
10482 return LowerDIV_Windows(
Op, DAG,
false);
10493 return LowerALUO(
Op, DAG);
10501 EVT MemVT = LD->getMemoryVT();
10502 if (Subtarget->hasMVEIntegerOps() &&
10503 (MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10504 MemVT == MVT::v16i1))
10507 auto Pair = LowerAEABIUnalignedLoad(
Op, DAG);
10513 return LowerSTORE(
Op, DAG, Subtarget);
10538 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10547 return LowerSPONENTRY(
Op, DAG);
10549 return LowerFP_TO_BF16(
Op, DAG);
10550 case ARMISD::WIN__DBZCHK:
return SDValue();
10553 return LowerCMP(
Op, DAG);
10555 return LowerABS(
Op, DAG);
10560 assert((
Op.getOperand(1).getValueType() == MVT::f16 ||
10561 Op.getOperand(1).getValueType() == MVT::bf16) &&
10562 "Expected custom lowering of rounding operations only for f16");
10565 {
Op.getOperand(0),
Op.getOperand(1)});
10566 return DAG.
getNode(
Op.getOpcode(),
DL, {Op.getValueType(), MVT::Other},
10567 {Ext.getValue(1), Ext.getValue(0)});
10574 unsigned IntNo =
N->getConstantOperandVal(0);
10576 if (IntNo == Intrinsic::arm_smlald)
10577 Opc = ARMISD::SMLALD;
10578 else if (IntNo == Intrinsic::arm_smlaldx)
10579 Opc = ARMISD::SMLALDX;
10580 else if (IntNo == Intrinsic::arm_smlsld)
10581 Opc = ARMISD::SMLSLD;
10582 else if (IntNo == Intrinsic::arm_smlsldx)
10583 Opc = ARMISD::SMLSLDX;
10589 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(3), dl, MVT::i32, MVT::i32);
10593 N->getOperand(1),
N->getOperand(2),
10605 switch (
N->getOpcode()) {
10612 Res = ExpandBITCAST(
N, DAG, Subtarget);
10621 Res = LowerREM(
N, DAG);
10625 Res = LowerDivRem(
SDValue(
N, 0), DAG);
10642 "can only expand DIV on Windows");
10654 Res = LowerAEABIUnalignedStore(
SDValue(
N, 0), DAG);
10683 "ROPI/RWPI not currently supported with SjLj");
10692 bool isThumb = Subtarget->isThumb();
10693 bool isThumb2 = Subtarget->
isThumb2();
10696 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10702 : &ARM::GPRRegClass;
10808 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
10811 MachineRegisterInfo *MRI = &MF->
getRegInfo();
10815 const TargetRegisterClass *TRC = Subtarget->isThumb() ? &ARM::tGPRRegClass
10816 : &ARM::GPRnopcRegClass;
10820 DenseMap<unsigned, SmallVector<MachineBasicBlock*, 2>> CallSiteNumToLPad;
10821 unsigned MaxCSNum = 0;
10822 for (MachineBasicBlock &BB : *MF) {
10828 for (MachineInstr &
II : BB) {
10829 if (!
II.isEHLabel())
10832 MCSymbol *Sym =
II.getOperand(0).getMCSymbol();
10833 if (!MF->hasCallSiteLandingPad(Sym))
continue;
10835 SmallVectorImpl<unsigned> &CallSiteIdxs = MF->getCallSiteLandingPad(Sym);
10836 for (
unsigned Idx : CallSiteIdxs) {
10837 CallSiteNumToLPad[Idx].push_back(&BB);
10838 MaxCSNum = std::max(MaxCSNum, Idx);
10845 std::vector<MachineBasicBlock*> LPadList;
10846 SmallPtrSet<MachineBasicBlock*, 32> InvokeBBs;
10847 LPadList.reserve(CallSiteNumToLPad.
size());
10848 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
10849 SmallVectorImpl<MachineBasicBlock*> &MBBList = CallSiteNumToLPad[
I];
10850 for (MachineBasicBlock *
MBB : MBBList) {
10851 LPadList.push_back(
MBB);
10856 assert(!LPadList.empty() &&
10857 "No landing pad destinations for the dispatch jump table!");
10860 MachineJumpTableInfo *JTI =
10867 MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock();
10870 MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock();
10872 BuildMI(TrapBB, dl,
TII->get(Subtarget->isThumb() ? ARM::tTRAP : ARM::TRAP));
10875 MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock();
10879 MF->insert(MF->end(), DispatchBB);
10880 MF->insert(MF->end(), DispContBB);
10881 MF->insert(MF->end(), TrapBB);
10885 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
10887 MachineMemOperand *FIMMOLd = MF->getMachineMemOperand(
10891 MachineInstrBuilder MIB;
10892 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
10894 const ARMBaseInstrInfo *AII =
static_cast<const ARMBaseInstrInfo*
>(
TII);
10904 unsigned NumLPads = LPadList.size();
10905 if (Subtarget->isThumb2()) {
10907 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
10913 if (NumLPads < 256) {
10914 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
10916 .
addImm(LPadList.size())
10920 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
10921 .
addImm(NumLPads & 0xFFFF)
10924 unsigned VReg2 = VReg1;
10925 if ((NumLPads & 0xFFFF0000) != 0) {
10927 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
10933 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
10939 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
10945 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
10950 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
10957 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
10961 }
else if (Subtarget->isThumb()) {
10963 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
10969 if (NumLPads < 256) {
10970 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
10975 MachineConstantPool *
ConstantPool = MF->getConstantPool();
10980 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
10981 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
10984 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
10988 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
10994 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
11000 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
11007 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
11012 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
11018 MachineMemOperand *JTMMOLd =
11023 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
11029 unsigned NewVReg6 = NewVReg5;
11030 if (IsPositionIndependent) {
11032 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
11039 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
11044 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
11050 if (NumLPads < 256) {
11051 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
11055 }
else if (Subtarget->hasV6T2Ops() &&
isUInt<16>(NumLPads)) {
11057 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
11058 .
addImm(NumLPads & 0xFFFF)
11061 unsigned VReg2 = VReg1;
11062 if ((NumLPads & 0xFFFF0000) != 0) {
11064 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
11070 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11075 MachineConstantPool *
ConstantPool = MF->getConstantPool();
11080 Align Alignment = MF->getDataLayout().getPrefTypeAlign(
Int32Ty);
11081 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11084 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
11089 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11101 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
11107 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
11111 MachineMemOperand *JTMMOLd =
11115 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
11122 if (IsPositionIndependent) {
11123 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11128 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11135 SmallPtrSet<MachineBasicBlock*, 8> SeenMBBs;
11136 for (MachineBasicBlock *CurMBB : LPadList) {
11137 if (SeenMBBs.
insert(CurMBB).second)
11144 for (MachineBasicBlock *BB : InvokeBBs) {
11148 SmallVector<MachineBasicBlock*, 4> Successors(BB->successors());
11149 while (!Successors.empty()) {
11150 MachineBasicBlock *SMBB = Successors.pop_back_val();
11152 BB->removeSuccessor(SMBB);
11158 BB->normalizeSuccProbs();
11165 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11166 if (!
II->isCall())
continue;
11168 DenseSet<unsigned> DefRegs;
11170 OI =
II->operands_begin(), OE =
II->operands_end();
11172 if (!OI->isReg())
continue;
11173 DefRegs.
insert(OI->getReg());
11176 MachineInstrBuilder MIB(*MF, &*
II);
11178 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11179 unsigned Reg = SavedRegs[i];
11180 if (Subtarget->isThumb2() &&
11181 !ARM::tGPRRegClass.contains(
Reg) &&
11182 !ARM::hGPRRegClass.contains(
Reg))
11184 if (Subtarget->isThumb1Only() && !ARM::tGPRRegClass.contains(
Reg))
11186 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(
Reg))
11198 for (MachineBasicBlock *MBBLPad : MBBLPads)
11199 MBBLPad->setIsEHPad(
false);
11202 MI.eraseFromParent();
11215static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11217 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11218 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11220 return LdSize == 4 ? ARM::tLDRi
11221 : LdSize == 2 ? ARM::tLDRHi
11222 : LdSize == 1 ? ARM::tLDRBi : 0;
11224 return LdSize == 4 ? ARM::t2LDR_POST
11225 : LdSize == 2 ? ARM::t2LDRH_POST
11226 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11227 return LdSize == 4 ? ARM::LDR_POST_IMM
11228 : LdSize == 2 ? ARM::LDRH_POST
11229 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11234static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11236 return StSize == 16 ? ARM::VST1q32wb_fixed
11237 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11239 return StSize == 4 ? ARM::tSTRi
11240 : StSize == 2 ? ARM::tSTRHi
11241 : StSize == 1 ? ARM::tSTRBi : 0;
11243 return StSize == 4 ? ARM::t2STR_POST
11244 : StSize == 2 ? ARM::t2STRH_POST
11245 : StSize == 1 ? ARM::t2STRB_POST : 0;
11246 return StSize == 4 ? ARM::STR_POST_IMM
11247 : StSize == 2 ? ARM::STRH_POST
11248 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11255 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11256 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11257 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11258 assert(LdOpc != 0 &&
"Should have a load opcode");
11265 }
else if (IsThumb1) {
11271 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11276 }
else if (IsThumb2) {
11296 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11297 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11298 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11299 assert(StOpc != 0 &&
"Should have a store opcode");
11301 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11306 }
else if (IsThumb1) {
11313 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11318 }
else if (IsThumb2) {
11319 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11325 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11340 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11346 unsigned SizeVal =
MI.getOperand(2).getImm();
11347 unsigned Alignment =
MI.getOperand(3).getImm();
11351 MachineRegisterInfo &MRI = MF->
getRegInfo();
11352 unsigned UnitSize = 0;
11353 const TargetRegisterClass *TRC =
nullptr;
11354 const TargetRegisterClass *VecTRC =
nullptr;
11356 bool IsThumb1 = Subtarget->isThumb1Only();
11357 bool IsThumb2 = Subtarget->isThumb2();
11358 bool IsThumb = Subtarget->isThumb();
11360 if (Alignment & 1) {
11362 }
else if (Alignment & 2) {
11367 Subtarget->hasNEON()) {
11368 if ((Alignment % 16 == 0) && SizeVal >= 16)
11370 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11379 bool IsNeon = UnitSize >= 8;
11380 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11382 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11383 : UnitSize == 8 ? &ARM::DPRRegClass
11386 unsigned BytesLeft = SizeVal % UnitSize;
11387 unsigned LoopSize = SizeVal - BytesLeft;
11389 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11393 unsigned srcIn = src;
11394 unsigned destIn = dest;
11395 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11400 IsThumb1, IsThumb2);
11402 IsThumb1, IsThumb2);
11410 for (
unsigned i = 0; i < BytesLeft; i++) {
11415 IsThumb1, IsThumb2);
11417 IsThumb1, IsThumb2);
11421 MI.eraseFromParent();
11447 MF->
insert(It, loopMBB);
11448 MF->
insert(It, exitMBB);
11451 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11462 if (Subtarget->useMovt()) {
11463 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11466 }
else if (Subtarget->genExecuteOnly()) {
11467 assert(IsThumb &&
"Non-thumb expected to have used movt");
11476 unsigned Idx =
ConstantPool->getConstantPoolIndex(
C, Alignment);
11477 MachineMemOperand *CPMMO =
11501 MachineBasicBlock *entryBB = BB;
11516 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11524 IsThumb1, IsThumb2);
11526 IsThumb1, IsThumb2);
11530 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11536 MachineInstrBuilder MIB =
11538 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11547 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11556 auto StartOfExit = exitMBB->
begin();
11560 unsigned srcIn = srcLoop;
11561 unsigned destIn = destLoop;
11562 for (
unsigned i = 0; i < BytesLeft; i++) {
11566 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11567 IsThumb1, IsThumb2);
11568 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11569 IsThumb1, IsThumb2);
11574 MI.eraseFromParent();
11582 const TargetInstrInfo &
TII = *Subtarget->getInstrInfo();
11585 assert(TM.getTargetTriple().isOSWindows() &&
11586 "__chkstk is only supported on Windows");
11587 assert(Subtarget->isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11607 RTLIB::LibcallImpl ChkStkLibcall =
getLibcallImpl(RTLIB::STACK_PROBE);
11608 if (ChkStkLibcall == RTLIB::Unsupported)
11612 switch (TM.getCodeModel()) {
11654 MI.eraseFromParent();
11663 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
11678 .
addReg(
MI.getOperand(0).getReg())
11686 MI.eraseFromParent();
11710 if (miI == BB->
end()) {
11712 if (Succ->isLiveIn(ARM::CPSR))
11718 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11731 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11738 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11745 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11748 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11749 .
addUse(TotalIterationsReg)
11756 return TotalIterationsReg;
11767 Register TotalIterationsReg,
bool IsMemcpy) {
11776 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11786 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11794 Register RemainingLoopIterationsReg =
11796 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11797 .
addUse(TotalIterationsReg)
11799 .
addUse(RemainingLoopIterationsReg)
11805 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11806 .
addUse(ElementCountReg)
11808 .
addUse(RemainingElementsReg)
11813 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11814 .
addUse(PredCounterPhiReg)
11819 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11820 .
addUse(PredCounterPhiReg)
11829 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
11838 SrcValueReg = OpSrcReg;
11840 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
11851 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
11852 .
addUse(LoopCounterPhiReg)
11855 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
11856 .
addUse(RemainingLoopIterationsReg)
11874 "Invalid call instruction for a KCFI check");
11877 switch (
MBBI->getOpcode()) {
11880 case ARM::BLX_pred:
11881 case ARM::BLX_noip:
11882 case ARM::BLX_pred_noip:
11884 TargetOp = &
MBBI->getOperand(0);
11886 case ARM::TCRETURNri:
11887 case ARM::TCRETURNrinotr12:
11888 case ARM::TAILJMPr:
11889 case ARM::TAILJMPr4:
11890 TargetOp = &
MBBI->getOperand(0);
11896 case ARM::tBLXr_noip:
11897 case ARM::tBX_CALL:
11898 TargetOp = &
MBBI->getOperand(2);
11901 case ARM::tTAILJMPr:
11902 TargetOp = &
MBBI->getOperand(0);
11908 assert(TargetOp && TargetOp->
isReg() &&
"Invalid target operand");
11912 unsigned KCFICheckOpcode;
11913 if (Subtarget->isThumb()) {
11914 if (Subtarget->isThumb2()) {
11915 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb2;
11917 KCFICheckOpcode = ARM::KCFI_CHECK_Thumb1;
11920 KCFICheckOpcode = ARM::KCFI_CHECK_ARM;
11934 bool isThumb2 = Subtarget->isThumb2();
11935 switch (
MI.getOpcode()) {
11942 case ARM::tLDR_postidx: {
11946 .
add(
MI.getOperand(2))
11947 .
add(
MI.getOperand(3))
11948 .
add(
MI.getOperand(4))
11949 .
add(
MI.getOperand(0))
11951 MI.eraseFromParent();
11955 case ARM::MVE_MEMCPYLOOPINST:
11956 case ARM::MVE_MEMSETLOOPINST: {
11986 Register OpDestReg =
MI.getOperand(0).getReg();
11987 Register OpSrcReg =
MI.getOperand(1).getReg();
11988 Register OpSizeReg =
MI.getOperand(2).getReg();
12008 if (TpExit == BB) {
12010 "block containing memcpy/memset Pseudo");
12020 genTPEntry(TpEntry, TpLoopBody, TpExit, OpSizeReg,
TII, dl, MRI);
12023 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
12025 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
12028 Properties.resetNoPHIs();
12040 MI.eraseFromParent();
12050 case ARM::t2STR_preidx:
12051 MI.setDesc(
TII->get(ARM::t2STR_PRE));
12053 case ARM::t2STRB_preidx:
12054 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
12056 case ARM::t2STRH_preidx:
12057 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
12060 case ARM::STRi_preidx:
12061 case ARM::STRBi_preidx: {
12062 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
12063 : ARM::STRB_PRE_IMM;
12065 unsigned Offset =
MI.getOperand(4).getImm();
12073 .
add(
MI.getOperand(0))
12074 .
add(
MI.getOperand(1))
12075 .
add(
MI.getOperand(2))
12077 .
add(
MI.getOperand(5))
12078 .
add(
MI.getOperand(6))
12080 MI.eraseFromParent();
12083 case ARM::STRr_preidx:
12084 case ARM::STRBr_preidx:
12085 case ARM::STRH_preidx: {
12087 switch (
MI.getOpcode()) {
12089 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
12090 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
12091 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
12096 MI.eraseFromParent();
12100 case ARM::tMOVCCr_pseudo: {
12118 F->insert(It, copy0MBB);
12119 F->insert(It, sinkMBB);
12122 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12128 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12144 .
addImm(
MI.getOperand(3).getImm())
12145 .
addReg(
MI.getOperand(4).getReg());
12160 .
addReg(
MI.getOperand(1).getReg())
12162 .
addReg(
MI.getOperand(2).getReg())
12165 MI.eraseFromParent();
12170 case ARM::BCCZi64: {
12176 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12181 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12185 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12191 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12195 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12205 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12214 MI.eraseFromParent();
12218 case ARM::Int_eh_sjlj_setjmp:
12219 case ARM::Int_eh_sjlj_setjmp_nofp:
12220 case ARM::tInt_eh_sjlj_setjmp:
12221 case ARM::t2Int_eh_sjlj_setjmp:
12222 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12225 case ARM::Int_eh_sjlj_setup_dispatch:
12226 EmitSjLjDispatchBlock(
MI, BB);
12228 case ARM::COPY_STRUCT_BYVAL_I32:
12230 return EmitStructByval(
MI, BB);
12231 case ARM::WIN__CHKSTK:
12232 return EmitLowered__chkstk(
MI, BB);
12233 case ARM::WIN__DBZCHK:
12234 return EmitLowered__dbzchk(
MI, BB);
12250 if (!
Node->hasAnyUseOfValue(0)) {
12251 MI.getOperand(0).setIsDead(
true);
12253 if (!
Node->hasAnyUseOfValue(1)) {
12254 MI.getOperand(1).setIsDead(
true);
12258 for (
unsigned I = 0;
I !=
MI.getOperand(4).
getImm(); ++
I) {
12260 : &ARM::GPRRegClass);
12267 if (
MI.getOpcode() == ARM::MEMCPY) {
12288 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12289 &&
"converted opcode should be the same except for cc_out"
12290 " (and, on Thumb1, pred)");
12298 if (Subtarget->isThumb1Only()) {
12299 for (
unsigned c =
MCID->getNumOperands() - 4; c--;) {
12300 MI.addOperand(
MI.getOperand(1));
12301 MI.removeOperand(1);
12305 for (
unsigned i =
MI.getNumOperands(); i--;) {
12307 if (
op.isReg() &&
op.isUse()) {
12310 MI.tieOperands(DefIdx, i);
12318 ccOutIdx =
MCID->getNumOperands() - 1;
12320 ccOutIdx =
MCID->getNumOperands() - 1;
12324 if (!
MI.hasOptionalDef() || !
MCID->operands()[ccOutIdx].isOptionalDef()) {
12325 assert(!NewOpc &&
"Optional cc_out operand required");
12330 bool definesCPSR =
false;
12331 bool deadCPSR =
false;
12332 for (
unsigned i =
MCID->getNumOperands(), e =
MI.getNumOperands(); i != e;
12336 definesCPSR =
true;
12339 MI.removeOperand(i);
12343 if (!definesCPSR) {
12344 assert(!NewOpc &&
"Optional cc_out operand required");
12347 assert(deadCPSR == !
Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12349 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12350 "expect uninitialized optional cc_out operand");
12352 if (!Subtarget->isThumb1Only())
12388 switch (
N->getOpcode()) {
12389 default:
return false;
12391 CC =
N->getOperand(0);
12413 EVT VT =
N->getValueType(0);
12414 CC =
N->getOperand(0);
12461 EVT VT =
N->getValueType(0);
12464 bool SwapSelectOps;
12466 NonConstantVal, DAG))
12472 OtherOp, NonConstantVal);
12478 CCOp, TrueVal, FalseVal);
12498 if (
N->getOpcode() == ARMISD::VUZP)
12502 if (
N->getOpcode() == ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12517 if (!
N->getValueType(0).is64BitVector())
12525 EVT VT =
N->getValueType(0);
12564 EVT VT =
N->getValueType(0);
12570 Opcode = Intrinsic::arm_neon_vpaddls;
12572 Opcode = Intrinsic::arm_neon_vpaddlu;
12600 EVT VT =
N->getValueType(0);
12615 unsigned nextIndex = 0;
12666 Ops.push_back(Vec);
12683 return DAG.
getNode(ExtOp, dl, VT, tmp);
12714 if (SRA.getOpcode() !=
ISD::SRA) {
12721 if (Const->getZExtValue() != 31)
12726 if (SRA.getOperand(0) !=
Mul)
12730 SDLoc dl(AddcNode);
12731 unsigned Opcode = 0;
12736 Opcode = ARMISD::SMLALBB;
12737 Op0 =
Mul.getOperand(0);
12738 Op1 =
Mul.getOperand(1);
12740 Opcode = ARMISD::SMLALBT;
12741 Op0 =
Mul.getOperand(0);
12742 Op1 =
Mul.getOperand(1).getOperand(0);
12744 Opcode = ARMISD::SMLALTB;
12745 Op0 =
Mul.getOperand(0).getOperand(0);
12746 Op1 =
Mul.getOperand(1);
12748 Opcode = ARMISD::SMLALTT;
12749 Op0 =
Mul->getOperand(0).getOperand(0);
12750 Op1 =
Mul->getOperand(1).getOperand(0);
12766 SDValue resNode(AddcNode, 0);
12794 AddeSubeNode->
getOpcode() == ARMISD::SUBE) &&
12795 "Expect an ADDE or SUBE");
12799 "ADDE node has the wrong inputs");
12803 if ((AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12804 AddcSubcNode->
getOpcode() != ARMISD::ADDC) ||
12805 (AddeSubeNode->
getOpcode() == ARMISD::SUBE &&
12806 AddcSubcNode->
getOpcode() != ARMISD::SUBC))
12818 "Expect ADDC with two result values. First: i32");
12822 if (AddeSubeNode->
getOpcode() == ARMISD::ADDE &&
12838 bool IsLeftOperandMUL =
false;
12843 IsLeftOperandMUL =
true;
12854 SDValue *LowAddSub =
nullptr;
12857 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
12860 if (IsLeftOperandMUL)
12861 HiAddSub = &AddeSubeOp1;
12863 HiAddSub = &AddeSubeOp0;
12868 if (AddcSubcOp0 == MULOp.
getValue(0)) {
12869 LoMul = &AddcSubcOp0;
12870 LowAddSub = &AddcSubcOp1;
12872 if (AddcSubcOp1 == MULOp.
getValue(0)) {
12873 LoMul = &AddcSubcOp1;
12874 LowAddSub = &AddcSubcOp0;
12882 if (AddcSubcNode == HiAddSub->getNode() ||
12898 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
12903 Ops.push_back(*HiAddSub);
12904 if (AddcSubcNode->
getOpcode() == ARMISD::SUBC) {
12905 FinalOpc = ARMISD::SMMLSR;
12907 FinalOpc = ARMISD::SMMLAR;
12912 return SDValue(AddeSubeNode, 0);
12913 }
else if (AddcSubcNode->
getOpcode() == ARMISD::SUBC)
12919 Ops.push_back(*LowAddSub);
12920 Ops.push_back(*HiAddSub);
12933 return SDValue(AddeSubeNode, 0);
12945 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
12950 if (AddcNode->
getOpcode() != ARMISD::ADDC)
12954 SDNode *UmlalNode =
nullptr;
12993 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
12998 SDNode* AddcNode =
N->getOperand(2).getNode();
12999 SDNode* AddeNode =
N->getOperand(3).getNode();
13000 if ((AddcNode->
getOpcode() == ARMISD::ADDC) &&
13001 (AddeNode->
getOpcode() == ARMISD::ADDE) &&
13007 {N->getOperand(0), N->getOperand(1),
13008 AddcNode->getOperand(0), AddcNode->getOperand(1)});
13018 if (
N->getOpcode() == ARMISD::SUBC &&
N->hasAnyUseOfValue(1)) {
13022 if (
LHS->getOpcode() == ARMISD::ADDE &&
13032 int32_t imm =
C->getSExtValue();
13033 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
13036 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDC) ? ARMISD::SUBC
13038 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
13053 int64_t imm =
C->getSExtValue();
13062 unsigned Opcode = (
N->getOpcode() == ARMISD::ADDE) ? ARMISD::SUBE
13064 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
13065 N->getOperand(0),
RHS,
N->getOperand(2));
13077 if (!Subtarget->hasMVEIntegerOps())
13090 SetCC =
N->getOperand(0);
13094 TrueVal =
N->getOperand(1);
13095 FalseVal =
N->getOperand(2);
13097 LHS =
N->getOperand(0);
13098 RHS =
N->getOperand(1);
13100 TrueVal =
N->getOperand(2);
13101 FalseVal =
N->getOperand(3);
13106 unsigned int Opcode = 0;
13110 Opcode = ARMISD::VMINVu;
13116 Opcode = ARMISD::VMINVs;
13122 Opcode = ARMISD::VMAXVu;
13128 Opcode = ARMISD::VMAXVs;
13135 switch (TrueVal->getOpcode()) {
13154 if (TrueVal !=
LHS || FalseVal !=
RHS)
13157 EVT LeftType =
LHS->getValueType(0);
13158 EVT RightType =
RHS->getValueType(0);
13161 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13165 if (VectorScalarType != MVT::i32)
13173 if (VectorScalarType != MVT::i32)
13186 EVT VT =
N->getValueType(0);
13194 Shft =
N->getOperand(0);
13201 Cmp.getOperand(0) !=
N->getOperand(1) ||
13202 Cmp.getOperand(1) !=
N->getOperand(2))
13204 Shft =
N->getOperand(1);
13216 ScalarType = MVT::i8;
13219 case (1 << 15) - 1:
13220 ScalarType = MVT::i16;
13223 case (1ULL << 31) - 1:
13224 ScalarType = MVT::i32;
13255 unsigned LegalLanes = 128 / (ShftAmt + 1);
13267 Inp0 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp0);
13268 Inp1 = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, LegalVecVT, Inp1);
13269 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13270 SDValue Trunc = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, ExtVecVT, VQDMULH);
13279 for (
unsigned I = 0;
I < NumParts; ++
I) {
13286 SDValue VQDMULH = DAG.
getNode(ARMISD::VQDMULH,
DL, LegalVecVT, Inp0, Inp1);
13296 if (!Subtarget->hasMVEIntegerOps())
13311 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13321 if (!Const || !Const->isOne())
13339 EVT VT =
N->getValueType(0);
13341 if (!Subtarget->hasMVEIntegerOps() ||
13370 Opc = Intrinsic::arm_mve_vctp64;
13373 Opc = Intrinsic::arm_mve_vctp32;
13376 Opc = Intrinsic::arm_mve_vctp16;
13379 Opc = Intrinsic::arm_mve_vctp8;
13433 EVT VT =
N->getValueType(0);
13439 switch (
Op.getOpcode()) {
13441 case ARMISD::VADDVs:
13442 case ARMISD::VADDVu:
13443 case ARMISD::VMLAVs:
13444 case ARMISD::VMLAVu:
13464 unsigned N0RedOp = 0;
13471 unsigned N1RedOp = 0;
13485 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13487 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13494 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13518 if (!BaseLocDecomp0.getBase() ||
13519 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13520 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13522 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13524 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13534 if (IsBefore < 0) {
13537 }
else if (IsBefore > 0) {
13550 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13560 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13570 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13572 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13579 if (!Subtarget->hasMVEIntegerOps())
13585 EVT VT =
N->getValueType(0);
13590 if (VT != MVT::i64)
13601 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13621 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13630 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N0, N1))
13632 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N0, N1))
13634 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVs, ARMISD::VADDLVAs, N1, N0))
13636 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVu, ARMISD::VADDLVAu, N1, N0))
13638 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N0, N1))
13640 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N0, N1))
13642 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVps, ARMISD::VADDLVAps, N1, N0))
13644 if (
SDValue M = MakeVecReduce(ARMISD::VADDLVpu, ARMISD::VADDLVApu, N1, N0))
13646 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N0, N1))
13648 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N0, N1))
13650 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVs, ARMISD::VMLALVAs, N1, N0))
13652 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVu, ARMISD::VMLALVAu, N1, N0))
13654 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N0, N1))
13656 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N0, N1))
13658 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVps, ARMISD::VMLALVAps, N1, N0))
13660 if (
SDValue M = MakeVecReduce(ARMISD::VMLALVpu, ARMISD::VMLALVApu, N1, N0))
13670 "Expected shift op");
13672 SDValue ShiftLHS =
N->getOperand(0);
13686 if (Subtarget->isThumb1Only()) {
13697 if (Const->getAPIntValue().ult(256))
13700 Const->getAPIntValue().sgt(-256))
13716 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13717 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13718 "Expected XOR(SHIFT) pattern");
13723 if (XorC && ShiftC) {
13724 unsigned MaskIdx, MaskLen;
13725 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13726 unsigned ShiftAmt = ShiftC->getZExtValue();
13727 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13728 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13729 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13730 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13740 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13742 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13743 "Expected shift-shift mask");
13745 if (!Subtarget->isThumb1Only())
13748 EVT VT =
N->getValueType(0);
13756 unsigned BinOpcode,
EVT VT,
unsigned SelectOpcode,
SDValue X,
13758 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT) &&
13763 if (!Subtarget->hasNEON()) {
13764 if (Subtarget->isThumb1Only())
13778 return Subtarget->hasVFP2Base();
13780 return Subtarget->hasVFP2Base();
13782 return Subtarget->hasFP64();
13785 return Subtarget->hasMVEFloatOps();
13814 if (ST->isThumb() && ST->isThumb1Only())
13818 for (
auto *U :
N->users()) {
13819 switch(U->getOpcode()) {
13837 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
13838 U->getOperand(1).getOpcode() ==
ISD::SHL)
13848 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
13855 if (!C1ShlC2 || !C2)
13858 APInt C2Int = C2->getAPIntValue();
13859 APInt C1Int = C1ShlC2->getAPIntValue();
13861 if (C2Int.
uge(C2Width))
13867 if ((C1Int & Mask) != C1Int)
13874 auto LargeImm = [](
const APInt &Imm) {
13875 unsigned Zeros = Imm.countl_zero() + Imm.countr_zero();
13876 return Imm.getBitWidth() - Zeros > 8;
13879 if (LargeImm(C1Int) || LargeImm(C2Int))
13891 SHL.dump();
N->dump());
13952 if (
Op.hasOneUse() && ShiftAmt &&
13953 ShiftAmt->
getZExtValue() ==
Op.getValueType().getScalarSizeInBits() - 1)
14011 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
14032 return DCI.
DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0), Negate);
14053 if (!Subtarget->hasVMLxForwarding())
14072 EVT VT =
N->getValueType(0);
14083 EVT VT =
N->getValueType(0);
14084 if (VT != MVT::v2i64)
14095 return Op->getOperand(0);
14109 And =
And->getOperand(0);
14114 Mask = Mask->getOperand(0);
14117 Mask.getValueType() != MVT::v4i32)
14123 return And->getOperand(0);
14128 if (
SDValue Op0 = IsSignExt(N0)) {
14129 if (
SDValue Op1 = IsSignExt(N1)) {
14130 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14131 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14132 return DAG.
getNode(ARMISD::VMULLs, dl, VT, New0a, New1a);
14135 if (
SDValue Op0 = IsZeroExt(N0)) {
14136 if (
SDValue Op1 = IsZeroExt(N1)) {
14137 SDValue New0a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op0);
14138 SDValue New1a = DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v4i32, Op1);
14139 return DAG.
getNode(ARMISD::VMULLu, dl, VT, New0a, New1a);
14151 EVT VT =
N->getValueType(0);
14152 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14163 if (VT != MVT::i32)
14170 int64_t MulAmt =
C->getSExtValue();
14173 ShiftAmt = ShiftAmt & (32 - 1);
14178 MulAmt >>= ShiftAmt;
14239 if (
N->getValueType(0) != MVT::i32)
14248 if (C1 == 255 || C1 == 65535)
14251 SDNode *N0 =
N->getOperand(0).getNode();
14265 if (!C2 || C2 >= 32)
14309 if (Trailing == C2 && C2 + C3 < 32) {
14322 if (Leading == C2 && C2 + C3 < 32) {
14350 EVT VT =
N->getValueType(0);
14354 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14357 APInt SplatBits, SplatUndef;
14358 unsigned SplatBitSize;
14360 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14361 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14362 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14363 SplatBitSize == 64) {
14370 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VbicVT,
N->getOperand(0));
14372 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vbic);
14397 if (!Subtarget->hasV6Ops() ||
14398 (Subtarget->isThumb() &&
14399 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14402 SDValue SRL = OR->getOperand(0);
14403 SDValue SHL = OR->getOperand(1);
14406 SRL = OR->getOperand(1);
14407 SHL = OR->getOperand(0);
14414 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14418 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14419 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14420 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14439 unsigned Opcode = 0;
14440 if (
isS16(OpS16, DAG))
14441 Opcode = ARMISD::SMULWB;
14443 Opcode = ARMISD::SMULWT;
14458 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14461 EVT VT =
N->getValueType(0);
14476 if (VT != MVT::i32)
14489 if (Mask == 0xffff)
14496 if ((Val & ~Mask) != Val)
14502 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00,
14521 (Mask == ~Mask2)) {
14524 if (Subtarget->hasDSP() &&
14525 (Mask == 0xffff || Mask == 0xffff0000))
14531 Res = DAG.
getNode(ARMISD::BFI,
DL, VT, N00, Res,
14538 (~Mask == Mask2)) {
14541 if (Subtarget->hasDSP() &&
14542 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14598 if (
N->getOpcode() == ARMISD::VCMP)
14600 else if (
N->getOpcode() == ARMISD::VCMPZ)
14608 return isValidMVECond(CC,
N->getOperand(0).getValueType().isFloatingPoint());
14615 EVT VT =
N->getValueType(0);
14620 auto IsFreelyInvertable = [&](
SDValue V) {
14621 if (V->getOpcode() == ARMISD::VCMP || V->getOpcode() == ARMISD::VCMPZ)
14627 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14645 if (AndOp.getOpcode() !=
ISD::AND)
14649 SDValue Mask = AndOp.getOperand(1);
14659 bool IsShiftRight =
false;
14662 if (ShiftOp.
getOpcode() == ARMISD::VSHRuIMM) {
14663 IsShiftRight =
true;
14666 }
else if (ShiftOp.
getOpcode() == ARMISD::VSHLIMM) {
14674 APInt RequiredMask = IsShiftRight
14677 if (MaskBits != RequiredMask)
14680 unsigned Opc = IsShiftRight ? ARMISD::VSRIIMM : ARMISD::VSLIIMM;
14690 EVT VT =
N->getValueType(0);
14696 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14697 VT == MVT::v8i1 || VT == MVT::v16i1))
14700 APInt SplatBits, SplatUndef;
14701 unsigned SplatBitSize;
14703 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14704 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14705 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14706 SplatBitSize == 64) {
14713 DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VorrVT,
N->getOperand(0));
14715 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Vorr);
14735 (Subtarget->hasMVEIntegerOps() &&
14736 (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32)))) {
14739 return ShiftInsert;
14743 return ShiftInsert;
14757 unsigned SplatBitSize;
14760 APInt SplatBits0, SplatBits1;
14764 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14765 HasAnyUndefs) && !HasAnyUndefs) {
14766 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14767 HasAnyUndefs) && !HasAnyUndefs) {
14772 SplatBits0 == ~SplatBits1) {
14780 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT, Result);
14802 EVT VT =
N->getValueType(0);
14817 if (Subtarget->hasMVEIntegerOps()) {
14845 assert(
N->getOpcode() == ARMISD::BFI);
14848 ToMask =
~N->getConstantOperandAPInt(2);
14868 unsigned LastActiveBitInA =
A.countr_zero();
14869 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
14870 return LastActiveBitInA - 1 == FirstActiveBitInB;
14875 APInt ToMask, FromMask;
14880 if (V.getOpcode() != ARMISD::BFI)
14883 APInt NewToMask, NewFromMask;
14885 if (NewFrom != From)
14889 if ((NewToMask & ToMask).getBoolValue())
14914 unsigned InvMask =
N->getConstantOperandVal(2);
14918 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
14919 "undefined behavior");
14920 unsigned Mask = (1u << Width) - 1;
14922 if ((Mask & (~Mask2)) == 0)
14924 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
14931 APInt ToMask1, FromMask1;
14934 APInt ToMask2, FromMask2;
14940 APInt NewFromMask = FromMask1 | FromMask2;
14941 APInt NewToMask = ToMask1 | ToMask2;
14943 EVT VT =
N->getValueType(0);
14946 if (NewFromMask[0] == 0)
14949 return DAG.
getNode(ARMISD::BFI, dl, VT, CombineBFI.getOperand(0), From1,
14957 if (
N->getOperand(0).getOpcode() == ARMISD::BFI) {
14958 APInt ToMask1 =
~N->getConstantOperandAPInt(2);
14959 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
14961 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
14965 EVT VT =
N->getValueType(0);
14968 N->getOperand(1),
N->getOperand(2));
14980 if (Cmp->getOpcode() != ARMISD::CMPZ || !
isNullConstant(Cmp->getOperand(1)))
14982 SDValue CSInc = Cmp->getOperand(0);
14992 if (CSInc.
getOpcode() == ARMISD::CSINC &&
15032 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
15033 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15036 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
15038 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15051 SDValue InDouble =
N->getOperand(0);
15052 if (InDouble.
getOpcode() == ARMISD::VMOVDRR && Subtarget->hasFP64())
15066 SDValue BasePtr = LD->getBasePtr();
15068 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
15069 LD->getAlign(), LD->getMemOperand()->getFlags());
15075 LD->getPointerInfo().getWithOffset(4),
15077 LD->getMemOperand()->getFlags());
15096 BV.
getOpcode() == ARMISD::VECTOR_REG_CAST) &&
15110 if (!Subtarget->
isLittle() && BVSwap)
15128 if (!Subtarget->
isLittle() && BVSwap)
15147 if (Op0.
getOpcode() == ARMISD::VMOVRRD &&
15160 if (Op0->
getOpcode() == ARMISD::VMOVrh)
15173 if (Copy.getValueType() == MVT::f32 &&
15175 bool HasGlue = Copy->getNumOperands() == 3;
15176 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
15177 HasGlue ? Copy->getOperand(2) :
SDValue()};
15178 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
15197 if (LN0->hasOneUse() && LN0->isUnindexed() &&
15198 LN0->getMemoryVT() == MVT::i16) {
15201 LN0->getBasePtr(), LN0->getMemOperand());
15219 EVT VT =
N->getValueType(0);
15253 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15254 for (
unsigned i = 0; i < NumElts; ++i) {
15255 SDNode *Elt =
N->getOperand(i).getNode();
15272 if (
N->getNumOperands() == 2)
15278 EVT VT =
N->getValueType(0);
15284 for (
unsigned i = 0; i < NumElts; ++i) {
15310 EVT VT =
N->getValueType(0);
15318 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15323 Use->getValueType(0).isFloatingPoint())
15331 unsigned NumOfBitCastedElts = 0;
15333 unsigned NumOfRelevantElts = NumElts;
15334 for (
unsigned Idx = 0; Idx < NumElts; ++Idx) {
15339 ++NumOfBitCastedElts;
15343 --NumOfRelevantElts;
15347 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15365 for (
unsigned Idx = 0 ; Idx < NumElts; ++Idx) {
15370 V->getOperand(0).getValueType() == MVT::i32)
15372 V = V.getOperand(0);
15389 EVT VT =
N->getValueType(0);
15394 if (
Op->getOpcode() == ARMISD::PREDICATE_CAST) {
15396 if (
Op->getOperand(0).getValueType() == VT)
15397 return Op->getOperand(0);
15398 return DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15405 DCI.
DAG.
getNode(ARMISD::PREDICATE_CAST, dl, VT,
Op->getOperand(0));
15412 if (
Op.getValueType() == MVT::i32) {
15423 EVT VT =
N->getValueType(0);
15428 if (ST->isLittle())
15432 if (
Op.getValueType() == VT)
15439 if (
Op->getOpcode() == ARMISD::VECTOR_REG_CAST) {
15441 if (
Op->getOperand(0).getValueType() == VT)
15442 return Op->getOperand(0);
15443 return DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, VT,
Op->getOperand(0));
15451 if (!Subtarget->hasMVEIntegerOps())
15454 EVT VT =
N->getValueType(0);
15462 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op0,
N->getOperand(2));
15468 return DAG.
getNode(ARMISD::VCMPZ, dl, VT, Op1,
15472 return DAG.
getNode(ARMISD::VCMP, dl, VT, Op1, Op0,
15485 EVT VT =
N->getValueType(0);
15486 SDNode *Elt =
N->getOperand(1).getNode();
15501 Vec, V,
N->getOperand(2));
15511 EVT VT =
N->getValueType(0);
15539 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15540 isa<ConstantSDNode>(V->getOperand(1)) &&
15541 V->getConstantOperandVal(1) == Lane + 1 &&
15542 V->getOperand(0).getResNo() == ResNo;
15544 if (OtherIt == Op0->
users().
end())
15549 SDValue OtherExt(*OtherIt, 0);
15561 DCI.
DAG.
getNode(ARMISD::VECTOR_REG_CAST, dl, MVT::v2f64, Op0),
15564 DCI.
DAG.
getNode(ARMISD::VMOVRRD, dl, {MVT::i32, MVT::i32},
F64);
15574 EVT VT =
N->getValueType(0);
15578 if (Op0->
getOpcode() == ARMISD::VDUP) {
15580 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15581 return DCI.
DAG.
getNode(ARMISD::VMOVhr, dl, VT,
X);
15582 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15583 return DCI.
DAG.
getNode(ARMISD::VMOVrh, dl, VT,
X);
15584 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15587 while (
X.getValueType() != VT &&
X->getOpcode() ==
ISD::BITCAST)
15588 X =
X->getOperand(0);
15589 if (
X.getValueType() == VT)
15597 return Op0.
getOperand(
N->getConstantOperandVal(1));
15607 unsigned Offset =
N->getConstantOperandVal(1);
15609 if (MOV.
getOpcode() == ARMISD::VMOVDRR)
15619 unsigned Idx =
N->getConstantOperandVal(1);
15633 EVT VT =
N->getValueType(0);
15636 if (
Op.getOpcode() == ARMISD::VGETLANEu &&
15638 Op.getOperand(0).getValueType().getScalarType())
15639 return DAG.
getNode(ARMISD::VGETLANEs,
SDLoc(
N), VT,
Op.getOperand(0),
15648 SDValue SubVec =
N->getOperand(1);
15649 uint64_t IdxVal =
N->getConstantOperandVal(2);
15660 if (IdxVal == 0 && Vec.
isUndef())
15666 (IdxVal != 0 && IdxVal != NumSubElts))
15697 ARMISD::VMOVN,
DL, VT,
15703 ARMISD::VMOVN,
DL, VT,
15739 EVT VT =
N->getValueType(0);
15750 unsigned HalfElts = NumElts/2;
15752 for (
unsigned n = 0; n < NumElts; ++n) {
15755 if (MaskElt < (
int)HalfElts)
15757 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
15758 NewElt = HalfElts + MaskElt - NumElts;
15801 bool SimpleConstIncOnly,
15809 bool isLoadOp =
true;
15810 bool isLaneOp =
false;
15813 bool hasAlignment =
true;
15814 unsigned NewOpc = 0;
15815 unsigned NumVecs = 0;
15816 if (
Target.isIntrinsic) {
15817 unsigned IntNo =
N->getConstantOperandVal(1);
15821 case Intrinsic::arm_neon_vld1:
15825 case Intrinsic::arm_neon_vld2:
15829 case Intrinsic::arm_neon_vld3:
15833 case Intrinsic::arm_neon_vld4:
15837 case Intrinsic::arm_neon_vld1x2:
15840 hasAlignment =
false;
15842 case Intrinsic::arm_neon_vld1x3:
15845 hasAlignment =
false;
15847 case Intrinsic::arm_neon_vld1x4:
15850 hasAlignment =
false;
15852 case Intrinsic::arm_neon_vld2dup:
15856 case Intrinsic::arm_neon_vld3dup:
15860 case Intrinsic::arm_neon_vld4dup:
15864 case Intrinsic::arm_neon_vld2lane:
15869 case Intrinsic::arm_neon_vld3lane:
15874 case Intrinsic::arm_neon_vld4lane:
15879 case Intrinsic::arm_neon_vst1:
15884 case Intrinsic::arm_neon_vst2:
15885 NewOpc = ARMISD::VST2_UPD;
15889 case Intrinsic::arm_neon_vst3:
15894 case Intrinsic::arm_neon_vst4:
15895 NewOpc = ARMISD::VST4_UPD;
15899 case Intrinsic::arm_neon_vst2lane:
15905 case Intrinsic::arm_neon_vst3lane:
15911 case Intrinsic::arm_neon_vst4lane:
15917 case Intrinsic::arm_neon_vst1x2:
15921 hasAlignment =
false;
15923 case Intrinsic::arm_neon_vst1x3:
15927 hasAlignment =
false;
15929 case Intrinsic::arm_neon_vst1x4:
15933 hasAlignment =
false;
15938 switch (
N->getOpcode()) {
15974 VecTy =
N->getValueType(0);
15975 }
else if (
Target.isIntrinsic) {
15976 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
15979 "Node has to be a load, a store, or an intrinsic!");
15980 VecTy =
N->getOperand(1).getValueType();
15988 if (isLaneOp || isVLDDUPOp)
15991 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
15997 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
16006 EVT AlignedVecTy = VecTy;
16026 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
16027 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
16038 Alignment =
Align(1);
16044 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16046 for (n = 0; n < NumResultVecs; ++n)
16047 Tys[n] = AlignedVecTy;
16048 Tys[n++] = MVT::i32;
16049 Tys[n] = MVT::Other;
16054 Ops.push_back(
N->getOperand(0));
16055 Ops.push_back(
N->getOperand(
Target.AddrOpIdx));
16060 Ops.push_back(StN->getValue());
16064 unsigned LastOperand =
16065 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
16066 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
16067 Ops.push_back(
N->getOperand(i));
16075 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::STORE) {
16086 for (
unsigned i = 0; i < NumResultVecs; ++i)
16091 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::LOAD) {
16092 SDValue &LdVal = NewResults[0];
16128 switch (
N->getOpcode()) {
16132 *Ptr =
N->getOperand(0);
16133 *CInc =
N->getOperand(1);
16140 *Ptr =
N->getOperand(1);
16141 *CInc =
N->getOperand(2);
16168 SDValue Addr =
N->getOperand(AddrOpIdx);
16179 unsigned ConstInc =
16184 if (BaseUpdates.
size() >= MaxBaseUpdates)
16204 unsigned UserOffset =
16207 if (!UserOffset || UserOffset <=
Offset)
16210 unsigned NewConstInc = UserOffset -
Offset;
16213 if (BaseUpdates.
size() >= MaxBaseUpdates)
16220 unsigned NumValidUpd = BaseUpdates.
size();
16221 for (
unsigned I = 0;
I < NumValidUpd;
I++) {
16232 return LHS.ConstInc <
RHS.ConstInc;
16261 unsigned IntNo =
N->getConstantOperandVal(1);
16262 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16264 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16287 bool isLoadOp =
true;
16288 unsigned NewOpc = 0;
16289 unsigned NumVecs = 0;
16293 case Intrinsic::arm_mve_vld2q:
16297 case Intrinsic::arm_mve_vld4q:
16301 case Intrinsic::arm_mve_vst2q:
16302 NewOpc = ARMISD::VST2_UPD;
16306 case Intrinsic::arm_mve_vst4q:
16307 NewOpc = ARMISD::VST4_UPD;
16316 VecTy =
N->getValueType(0);
16318 VecTy =
N->getOperand(3).getValueType();
16332 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16334 for (n = 0; n < NumResultVecs; ++n)
16336 Tys[n++] = MVT::i32;
16337 Tys[n] = MVT::Other;
16342 Ops.push_back(
N->getOperand(0));
16343 Ops.push_back(
N->getOperand(2));
16344 Ops.push_back(Inc);
16346 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16347 Ops.push_back(
N->getOperand(i));
16354 for (
unsigned i = 0; i < NumResultVecs; ++i)
16373 EVT VT =
N->getValueType(0);
16379 SDNode *VLD =
N->getOperand(0).getNode();
16382 unsigned NumVecs = 0;
16383 unsigned NewOpc = 0;
16385 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16388 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16391 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16403 if (
Use.getResNo() == NumVecs)
16406 if (
User->getOpcode() != ARMISD::VDUPLANE ||
16407 VLDLaneNo !=
User->getConstantOperandVal(1))
16414 for (n = 0; n < NumVecs; ++n)
16416 Tys[n] = MVT::Other;
16426 unsigned ResNo =
Use.getResNo();
16428 if (ResNo == NumVecs)
16435 std::vector<SDValue> VLDDupResults;
16436 for (
unsigned n = 0; n < NumVecs; ++n)
16450 EVT VT =
N->getValueType(0);
16453 if (Subtarget->hasMVEIntegerOps()) {
16457 ExtractVT = MVT::i32;
16459 N->getOperand(0),
N->getOperand(1));
16471 Op =
Op.getOperand(0);
16472 if (
Op.getOpcode() != ARMISD::VMOVIMM &&
Op.getOpcode() != ARMISD::VMVNIMM)
16476 unsigned EltSize =
Op.getScalarValueSizeInBits();
16478 unsigned Imm =
Op.getConstantOperandVal(0);
16494 if (Subtarget->hasMVEIntegerOps()) {
16497 if (
Op.getValueType() == MVT::f32)
16498 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16500 else if (
Op.getValueType() == MVT::f16)
16501 return DAG.
getNode(ARMISD::VDUP, dl,
N->getValueType(0),
16502 DAG.
getNode(ARMISD::VMOVrh, dl, MVT::i32,
Op));
16505 if (!Subtarget->hasNEON())
16512 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16513 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16514 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16519 LD->getMemoryVT(), LD->getMemOperand());
16530 EVT VT =
N->getValueType(0);
16552 assert(StVT != VT &&
"Cannot truncate to the same type");
16562 if (0 != (NumElems * FromEltSz) % ToEltSz)
16565 unsigned SizeRatio = FromEltSz / ToEltSz;
16570 NumElems * SizeRatio);
16576 for (
unsigned i = 0; i < NumElems; ++i)
16590 MVT StoreType = MVT::i8;
16592 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16612 for (
unsigned I = 0;
I <
E;
I++) {
16643 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16646 unsigned NumElements = 4;
16663 unsigned Off0 = Rev ? NumElts : 0;
16664 unsigned Off1 = Rev ? 0 : NumElts;
16666 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16667 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16669 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16677 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16697 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16708 Extract = DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v4i32, FPTrunc);
16712 NewToVT, Alignment, MMOFlags, AAInfo);
16745 unsigned NewOffset =
16753 NewToVT, Alignment, MMOFlags, AAInfo);
16775 {Extract.getOperand(0), Extract.getOperand(1)});
16806 if (Subtarget->hasNEON())
16810 if (Subtarget->hasMVEFloatOps())
16814 if (Subtarget->hasMVEIntegerOps()) {
16889 if (!Subtarget->hasNEON())
16893 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
16901 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
16903 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
16904 uint32_t IntBits = IntTy.getSizeInBits();
16905 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
16906 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
16917 if (
C == -1 ||
C == 0 ||
C > 32)
16922 unsigned IntrinsicOpcode = isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
16923 Intrinsic::arm_neon_vcvtfp2fxu;
16926 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
16929 if (IntBits < FloatBits)
16937 if (!Subtarget->hasMVEFloatOps())
16945 EVT VT =
N->getValueType(0);
16950 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
16952 Op.getOperand(0).getOpcode() != ARMISD::VMOVIMM)
16954 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
16955 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
16957 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
16970 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
16981 EVT VT =
N->getValueType(0);
16984 if (!
N->getFlags().hasAllowReassociation())
16991 unsigned Opc =
A.getConstantOperandVal(0);
16992 if (
Opc != Intrinsic::arm_mve_vcmlaq)
16997 A.getOperand(3),
A.getOperand(4));
17029 if (!Subtarget->hasNEON())
17033 unsigned OpOpcode =
Op.getNode()->getOpcode();
17034 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
17038 SDValue ConstVec =
N->getOperand(1);
17042 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
17044 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
17045 uint32_t IntBits = IntTy.getSizeInBits();
17046 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17047 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17067 int32_t
C = IntVal.exactLogBase2();
17068 if (
C == -1 ||
C == 0 ||
C > 32)
17074 if (IntBits < FloatBits)
17076 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
17078 unsigned IntrinsicOpcode = isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
17079 : Intrinsic::arm_neon_vcvtfxu2fp;
17087 if (!ST->hasMVEIntegerOps())
17091 EVT ResVT =
N->getValueType(0);
17119 EVT AVT =
A.getValueType();
17125 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
17126 EVT AVT =
A.getValueType();
17136 auto IsVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes) {
17137 if (ResVT != RetTy || N0->
getOpcode() != ExtendCode)
17140 if (ExtTypeMatches(
A, ExtTypes))
17141 return ExtendIfNeeded(
A, ExtendCode);
17144 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
17154 if (ExtTypeMatches(
A, ExtTypes))
17155 return ExtendIfNeeded(
A, ExtendCode);
17158 auto IsVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17168 if (ResVT != RetTy)
17171 if (
Mul->getOpcode() == ExtendCode &&
17172 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17174 Mul =
Mul->getOperand(0);
17183 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17184 A = ExtendIfNeeded(
A, ExtendCode);
17185 B = ExtendIfNeeded(
B, ExtendCode);
17190 auto IsPredVMLAV = [&](
MVT RetTy,
unsigned ExtendCode,
ArrayRef<MVT> ExtTypes,
17203 if (
Mul->getOpcode() == ExtendCode &&
17204 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17206 Mul =
Mul->getOperand(0);
17215 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17216 A = ExtendIfNeeded(
A, ExtendCode);
17217 B = ExtendIfNeeded(
B, ExtendCode);
17228 EVT VT =
Ops[0].getValueType();
17229 if (VT == MVT::v16i8) {
17230 assert((Opcode == ARMISD::VMLALVs || Opcode == ARMISD::VMLALVu) &&
17231 "Unexpected illegal long reduction opcode");
17232 bool IsUnsigned = Opcode == ARMISD::VMLALVu;
17244 DAG.
getNode(IsUnsigned ? ARMISD::VMLALVAu : ARMISD::VMLALVAs, dl,
17257 return DAG.
getNode(ARMISD::VMLAVs, dl, ResVT,
A,
B);
17259 return DAG.
getNode(ARMISD::VMLAVu, dl, ResVT,
A,
B);
17260 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17262 return Create64bitNode(ARMISD::VMLALVs, {
A,
B});
17263 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17265 return Create64bitNode(ARMISD::VMLALVu, {
A,
B});
17268 DAG.
getNode(ARMISD::VMLAVs, dl, MVT::i32,
A,
B));
17271 DAG.
getNode(ARMISD::VMLAVu, dl, MVT::i32,
A,
B));
17275 return DAG.
getNode(ARMISD::VMLAVps, dl, ResVT,
A,
B, Mask);
17278 return DAG.
getNode(ARMISD::VMLAVpu, dl, ResVT,
A,
B, Mask);
17281 return Create64bitNode(ARMISD::VMLALVps, {
A,
B, Mask});
17284 return Create64bitNode(ARMISD::VMLALVpu, {
A,
B, Mask});
17287 DAG.
getNode(ARMISD::VMLAVps, dl, MVT::i32,
A,
B, Mask));
17290 DAG.
getNode(ARMISD::VMLAVpu, dl, MVT::i32,
A,
B, Mask));
17293 return DAG.
getNode(ARMISD::VADDVs, dl, ResVT,
A);
17295 return DAG.
getNode(ARMISD::VADDVu, dl, ResVT,
A);
17297 return Create64bitNode(ARMISD::VADDLVs, {
A});
17299 return Create64bitNode(ARMISD::VADDLVu, {
A});
17302 DAG.
getNode(ARMISD::VADDVs, dl, MVT::i32,
A));
17305 DAG.
getNode(ARMISD::VADDVu, dl, MVT::i32,
A));
17308 return DAG.
getNode(ARMISD::VADDVps, dl, ResVT,
A, Mask);
17310 return DAG.
getNode(ARMISD::VADDVpu, dl, ResVT,
A, Mask);
17312 return Create64bitNode(ARMISD::VADDLVps, {
A, Mask});
17314 return Create64bitNode(ARMISD::VADDLVpu, {
A, Mask});
17317 DAG.
getNode(ARMISD::VADDVps, dl, MVT::i32,
A, Mask));
17320 DAG.
getNode(ARMISD::VADDVpu, dl, MVT::i32,
A, Mask));
17327 Op =
Op->getOperand(1);
17329 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17331 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17348 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17350 if (!Shuf || !Shuf->getOperand(1).isUndef())
17355 APInt SetElts(Mask.size(), 0);
17356 for (
int E : Mask) {
17364 if (
N->getNumOperands() != VecOp + 1) {
17366 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17372 if (
Op.getValueType().isVector())
17373 Ops.push_back(
Op.getOperand(0));
17384 unsigned IsTop =
N->getConstantOperandVal(2);
17391 if (Op0->
isUndef() && !IsTop)
17396 if ((Op1->
getOpcode() == ARMISD::VQMOVNs ||
17397 Op1->
getOpcode() == ARMISD::VQMOVNu) &&
17405 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17407 APInt Op0DemandedElts =
17408 IsTop ? Op1DemandedElts
17423 unsigned IsTop =
N->getConstantOperandVal(2);
17425 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17426 APInt Op0DemandedElts =
17438 EVT VT =
N->getValueType(0);
17445 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17446 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17450 LHS.getOperand(0),
RHS.getOperand(0));
17465 int ShiftAmt =
C->getSExtValue();
17466 if (ShiftAmt == 0) {
17472 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17473 unsigned NewOpcode =
17474 N->getOpcode() == ARMISD::LSLL ? ARMISD::LSRL : ARMISD::LSLL;
17489 unsigned IntNo =
N->getConstantOperandVal(0);
17500 case Intrinsic::arm_neon_vshifts:
17501 case Intrinsic::arm_neon_vshiftu:
17502 case Intrinsic::arm_neon_vrshifts:
17503 case Intrinsic::arm_neon_vrshiftu:
17504 case Intrinsic::arm_neon_vrshiftn:
17505 case Intrinsic::arm_neon_vqshifts:
17506 case Intrinsic::arm_neon_vqshiftu:
17507 case Intrinsic::arm_neon_vqshiftsu:
17508 case Intrinsic::arm_neon_vqshiftns:
17509 case Intrinsic::arm_neon_vqshiftnu:
17510 case Intrinsic::arm_neon_vqshiftnsu:
17511 case Intrinsic::arm_neon_vqrshiftns:
17512 case Intrinsic::arm_neon_vqrshiftnu:
17513 case Intrinsic::arm_neon_vqrshiftnsu: {
17514 EVT VT =
N->getOperand(1).getValueType();
17516 unsigned VShiftOpc = 0;
17519 case Intrinsic::arm_neon_vshifts:
17520 case Intrinsic::arm_neon_vshiftu:
17522 VShiftOpc = ARMISD::VSHLIMM;
17525 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17526 VShiftOpc = (IntNo == Intrinsic::arm_neon_vshifts ? ARMISD::VSHRsIMM
17527 : ARMISD::VSHRuIMM);
17532 case Intrinsic::arm_neon_vrshifts:
17533 case Intrinsic::arm_neon_vrshiftu:
17538 case Intrinsic::arm_neon_vqshifts:
17539 case Intrinsic::arm_neon_vqshiftu:
17544 case Intrinsic::arm_neon_vqshiftsu:
17549 case Intrinsic::arm_neon_vrshiftn:
17550 case Intrinsic::arm_neon_vqshiftns:
17551 case Intrinsic::arm_neon_vqshiftnu:
17552 case Intrinsic::arm_neon_vqshiftnsu:
17553 case Intrinsic::arm_neon_vqrshiftns:
17554 case Intrinsic::arm_neon_vqrshiftnu:
17555 case Intrinsic::arm_neon_vqrshiftnsu:
17567 case Intrinsic::arm_neon_vshifts:
17568 case Intrinsic::arm_neon_vshiftu:
17571 case Intrinsic::arm_neon_vrshifts:
17572 VShiftOpc = ARMISD::VRSHRsIMM;
17574 case Intrinsic::arm_neon_vrshiftu:
17575 VShiftOpc = ARMISD::VRSHRuIMM;
17577 case Intrinsic::arm_neon_vrshiftn:
17578 VShiftOpc = ARMISD::VRSHRNIMM;
17580 case Intrinsic::arm_neon_vqshifts:
17581 VShiftOpc = ARMISD::VQSHLsIMM;
17583 case Intrinsic::arm_neon_vqshiftu:
17584 VShiftOpc = ARMISD::VQSHLuIMM;
17586 case Intrinsic::arm_neon_vqshiftsu:
17587 VShiftOpc = ARMISD::VQSHLsuIMM;
17589 case Intrinsic::arm_neon_vqshiftns:
17590 VShiftOpc = ARMISD::VQSHRNsIMM;
17592 case Intrinsic::arm_neon_vqshiftnu:
17593 VShiftOpc = ARMISD::VQSHRNuIMM;
17595 case Intrinsic::arm_neon_vqshiftnsu:
17596 VShiftOpc = ARMISD::VQSHRNsuIMM;
17598 case Intrinsic::arm_neon_vqrshiftns:
17599 VShiftOpc = ARMISD::VQRSHRNsIMM;
17601 case Intrinsic::arm_neon_vqrshiftnu:
17602 VShiftOpc = ARMISD::VQRSHRNuIMM;
17604 case Intrinsic::arm_neon_vqrshiftnsu:
17605 VShiftOpc = ARMISD::VQRSHRNsuIMM;
17610 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17611 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
17614 case Intrinsic::arm_neon_vshiftins: {
17615 EVT VT =
N->getOperand(1).getValueType();
17617 unsigned VShiftOpc = 0;
17620 VShiftOpc = ARMISD::VSLIIMM;
17621 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
17622 VShiftOpc = ARMISD::VSRIIMM;
17628 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17629 N->getOperand(1),
N->getOperand(2),
17633 case Intrinsic::arm_neon_vqrshifts:
17634 case Intrinsic::arm_neon_vqrshiftu:
17638 case Intrinsic::arm_neon_vbsl: {
17640 return DAG.
getNode(ARMISD::VBSP, dl,
N->getValueType(0),
N->getOperand(1),
17641 N->getOperand(2),
N->getOperand(3));
17643 case Intrinsic::arm_mve_vqdmlah:
17644 case Intrinsic::arm_mve_vqdmlash:
17645 case Intrinsic::arm_mve_vqrdmlah:
17646 case Intrinsic::arm_mve_vqrdmlash:
17647 case Intrinsic::arm_mve_vmla_n_predicated:
17648 case Intrinsic::arm_mve_vmlas_n_predicated:
17649 case Intrinsic::arm_mve_vqdmlah_predicated:
17650 case Intrinsic::arm_mve_vqdmlash_predicated:
17651 case Intrinsic::arm_mve_vqrdmlah_predicated:
17652 case Intrinsic::arm_mve_vqrdmlash_predicated: {
17657 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
17664 case Intrinsic::arm_mve_minv:
17665 case Intrinsic::arm_mve_maxv:
17666 case Intrinsic::arm_mve_minav:
17667 case Intrinsic::arm_mve_maxav:
17668 case Intrinsic::arm_mve_minv_predicated:
17669 case Intrinsic::arm_mve_maxv_predicated:
17670 case Intrinsic::arm_mve_minav_predicated:
17671 case Intrinsic::arm_mve_maxav_predicated: {
17674 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
17681 case Intrinsic::arm_mve_addv: {
17684 bool Unsigned =
N->getConstantOperandVal(2);
17685 unsigned Opc =
Unsigned ? ARMISD::VADDVu : ARMISD::VADDVs;
17689 case Intrinsic::arm_mve_addlv:
17690 case Intrinsic::arm_mve_addlv_predicated: {
17693 bool Unsigned =
N->getConstantOperandVal(2);
17694 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
17695 (
Unsigned ? ARMISD::VADDLVu : ARMISD::VADDLVs) :
17696 (
Unsigned ? ARMISD::VADDLVpu : ARMISD::VADDLVps);
17699 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
17701 Ops.push_back(
N->getOperand(i));
17722 EVT VT =
N->getValueType(0);
17724 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
17725 N->getOperand(0)->getOpcode() ==
ISD::AND &&
17726 N->getOperand(0)->hasOneUse()) {
17743 if (AndMask == 255 || AndMask == 65535)
17747 if (MaskedBits > ShiftAmt) {
17762 if (ST->hasMVEIntegerOps())
17767 switch (
N->getOpcode()) {
17773 return DAG.
getNode(ARMISD::VSHLIMM, dl, VT,
N->getOperand(0),
17780 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
17781 unsigned VShiftOpc =
17782 (
N->getOpcode() ==
ISD::SRA ? ARMISD::VSHRsIMM : ARMISD::VSHRuIMM);
17784 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
17800 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
17803 EVT FromVT = LD->getValueType(0);
17804 EVT ToVT =
N->getValueType(0);
17811 unsigned NumElements = 0;
17812 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
17814 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
17816 if (NumElements == 0 ||
17826 SDValue BasePtr = LD->getBasePtr();
17827 Align Alignment = LD->getBaseAlign();
17848 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
17849 Alignment, MMOFlags, AAInfo);
17855 if (FromEltVT == MVT::f16) {
17858 for (
unsigned i = 0; i < Loads.
size(); i++) {
17860 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, MVT::v8f16, Loads[i]);
17884 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
17888 EVT VT =
N->getValueType(0);
17892 if (VT == MVT::i32 &&
17893 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
17898 switch (
N->getOpcode()) {
17901 Opc = ARMISD::VGETLANEs;
17905 Opc = ARMISD::VGETLANEu;
17912 if (ST->hasMVEIntegerOps())
17921 if (ST->hasMVEFloatOps())
17932 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
17936 EVT VT =
Op.getValueType();
17939 if (VT != MVT::i32 ||
17952 APInt MaxC = Max.getConstantOperandAPInt(1);
17955 !(MinC + 1).isPowerOf2())
17973 EVT VT =
N->getValueType(0);
17976 if (VT == MVT::i32)
17979 if (!ST->hasMVEIntegerOps())
17985 if (VT != MVT::v4i32 && VT != MVT::v8i16)
17988 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
17996 if (VT == MVT::v4i32)
17997 SaturateC =
APInt(32, (1 << 15) - 1,
true);
17999 SaturateC =
APInt(16, (1 << 7) - 1,
true);
18006 MaxC != ~SaturateC)
18011 if (IsSignedSaturate(
N, N0.
getNode())) {
18014 if (VT == MVT::v4i32) {
18015 HalfVT = MVT::v8i16;
18016 ExtVT = MVT::v4i16;
18018 HalfVT = MVT::v16i8;
18033 auto IsUnsignedSaturate = [&](
SDNode *Min) {
18039 if (VT == MVT::v4i32)
18040 SaturateC =
APInt(32, (1 << 16) - 1,
true);
18042 SaturateC =
APInt(16, (1 << 8) - 1,
true);
18051 if (IsUnsignedSaturate(
N)) {
18055 if (VT == MVT::v4i32) {
18056 HalfVT = MVT::v8i16;
18057 ExtConst = 0x0000FFFF;
18059 HalfVT = MVT::v16i8;
18081 const APInt *CV = &
C->getAPIntValue();
18138 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
18145 if ((OrCI & Known.
Zero) != OrCI)
18151 EVT VT =
X.getValueType();
18152 unsigned BitInX = AndC->
logBase2();
18160 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
18161 BitInY < NumActiveBits; ++BitInY) {
18162 if (OrCI[BitInY] == 0)
18165 Mask.setBit(BitInY);
18166 V = DAG.
getNode(ARMISD::BFI, dl, VT, V,
X,
18182 switch (
N->getOpcode()) {
18197 if (Const->isZero())
18199 else if (Const->isOne())
18207 unsigned IntOp =
N.getConstantOperandVal(1);
18208 if (IntOp != Intrinsic::test_start_loop_iterations &&
18209 IntOp != Intrinsic::loop_decrement_reg)
18235 bool Negate =
false;
18241 Cond =
N->getOperand(1);
18242 Dest =
N->getOperand(2);
18246 Cond =
N->getOperand(2);
18247 Dest =
N->getOperand(4);
18249 if (!Const->isOne() && !Const->isZero())
18251 Imm = Const->getZExtValue();
18279 assert((IsTrueIfZero(CC, Imm) || IsFalseIfZero(CC, Imm)) &&
18280 "unsupported condition");
18285 unsigned IntOp =
Int->getConstantOperandVal(1);
18286 assert((
N->hasOneUse() &&
N->user_begin()->getOpcode() ==
ISD::BR) &&
18287 "expected single br user");
18288 SDNode *Br = *
N->user_begin();
18298 if (IntOp == Intrinsic::test_start_loop_iterations) {
18300 SDValue Setup = DAG.
getNode(ARMISD::WLSSETUP, dl, MVT::i32, Elements);
18302 if (IsTrueIfZero(CC, Imm)) {
18304 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18308 UpdateUncondBr(Br, Dest, DAG);
18310 SDValue Ops[] = {Chain, Setup, OtherTarget};
18311 Res = DAG.
getNode(ARMISD::WLS, dl, MVT::Other,
Ops);
18323 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18327 SDValue Target = IsFalseIfZero(CC, Imm) ? Dest : OtherTarget;
18331 if (
Target == OtherTarget)
18332 UpdateUncondBr(Br, Dest, DAG);
18338 return DAG.
getNode(ARMISD::LE, dl, MVT::Other, EndArgs);
18347 if (Cmp.getOpcode() != ARMISD::CMPZ)
18352 SDValue LHS = Cmp.getOperand(0);
18353 SDValue RHS = Cmp.getOperand(1);
18362 LHS->getOperand(0)->getOpcode() == ARMISD::CMOV &&
18363 LHS->getOperand(0)->hasOneUse() &&
18367 return DAG.
getNode(ARMISD::BRCOND, dl, MVT::Other, Chain, BB,
18379 EVT VT =
N->getValueType(0);
18380 SDValue FalseVal =
N->getOperand(0);
18381 SDValue TrueVal =
N->getOperand(1);
18389 matchCSET(Opcode, InvertCond, TrueVal, FalseVal, Subtarget)) {
18396 return DAG.
getNode(Opcode, dl, VT, CSetOp, CSetOp, ARMcc, Cmp);
18399 if (Cmp.getOpcode() != ARMISD::CMPZ)
18403 SDValue LHS = Cmp.getOperand(0);
18404 SDValue RHS = Cmp.getOperand(1);
18408 if (!Subtarget->isThumb1Only() && Subtarget->hasV6T2Ops()) {
18432 if (CC ==
ARMCC::NE && FalseVal == RHS && FalseVal != LHS) {
18433 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, TrueVal, ARMcc, Cmp);
18434 }
else if (CC ==
ARMCC::EQ && TrueVal == RHS) {
18437 Res = DAG.
getNode(ARMISD::CMOV, dl, VT, LHS, FalseVal, ARMcc, NewCmp);
18442 if (CC ==
ARMCC::NE && LHS.getOpcode() == ARMISD::CMOV && LHS->hasOneUse() &&
18445 return DAG.
getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal,
18446 LHS->getOperand(2), LHS->getOperand(3));
18456 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18460 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18462 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18471 if (!Subtarget->isThumb1Only() && Subtarget->hasV5TOps()) {
18504 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, TrueVal, ARMcc,
18516 Res = DAG.
getNode(ARMISD::CMOV, dl, VT,
Sub, FalseVal,
18536 const APInt *TrueConst;
18537 if (Subtarget->isThumb1Only() && CC ==
ARMCC::NE &&
18538 ((FalseVal.getOpcode() == ARMISD::SUBC && FalseVal.getOperand(0) == LHS &&
18539 FalseVal.getOperand(1) == RHS) ||
18543 unsigned ShiftAmount = TrueConst->
logBase2();
18558 if (Known.
Zero == 0xfffffffe)
18561 else if (Known.
Zero == 0xffffff00)
18564 else if (Known.
Zero == 0xffff0000)
18577 EVT DstVT =
N->getValueType(0);
18580 if (ST->hasMVEIntegerOps() && Src.getOpcode() == ARMISD::VDUP) {
18581 EVT SrcVT = Src.getValueType();
18583 return DAG.
getNode(ARMISD::VDUP,
SDLoc(
N), DstVT, Src.getOperand(0));
18588 if (Src.getOpcode() == ARMISD::VECTOR_REG_CAST &&
18589 Src.getOperand(0).getValueType().getScalarSizeInBits() <=
18590 Src.getValueType().getScalarSizeInBits())
18591 Src = Src.getOperand(0);
18595 EVT SrcVT = Src.getValueType();
18596 if ((Src.getOpcode() == ARMISD::VMOVIMM ||
18597 Src.getOpcode() == ARMISD::VMVNIMM ||
18598 Src.getOpcode() == ARMISD::VMOVFPIMM) &&
18601 return DAG.
getNode(ARMISD::VECTOR_REG_CAST,
SDLoc(
N), DstVT, Src);
18615 EVT VT =
N->getValueType(0);
18623 if (
N->getNumOperands() == 2 &&
18627 N->getOperand(0).getOperand(1),
18628 N->getOperand(1).getOperand(0),
18629 N->getOperand(1).getOperand(1));
18632 if (
N->getNumOperands() == 2 &&
18638 if (S0->getOperand(0) ==
S1->getOperand(0) &&
18639 S0->getOperand(1) ==
S1->getOperand(1)) {
18642 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
18646 ARMISD::VMOVN,
DL, VT,
18647 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18648 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18652 ARMISD::VMOVN,
DL, VT,
18653 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(1)),
18654 DAG.
getNode(ARMISD::VECTOR_REG_CAST,
DL, VT, S0->getOperand(0)),
18662 return Op.getOpcode() == ISD::BUILD_VECTOR ||
18663 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
18664 (Op.getOpcode() == ISD::BITCAST &&
18665 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
18668 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
18670 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
18688 int NumIns =
N->getNumOperands();
18689 assert((NumIns == 2 || NumIns == 4) &&
18690 "Expected 2 or 4 inputs to an MVETrunc");
18692 if (
N->getNumOperands() == 4)
18696 for (
int I = 0;
I < NumIns;
I++) {
18698 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18703 Ptr, MPI, StoreVT,
Align(4));
18718 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
18721 EVT FromVT = LD->getMemoryVT();
18722 EVT ToVT =
N->getValueType(0);
18729 unsigned NumElements = 0;
18730 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
18732 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
18734 assert(NumElements != 0);
18740 LD->getExtensionType() != NewExtType)
18747 SDValue BasePtr = LD->getBasePtr();
18748 Align Alignment = LD->getBaseAlign();
18767 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18768 Alignment, MMOFlags, AAInfo);
18784 EVT VT =
N->getValueType(0);
18786 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
18787 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
18789 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18791 auto Extend = [&](
SDValue V) {
18800 if (
N->getOperand(0).getOpcode() == ARMISD::VDUP) {
18801 SDValue Ext = Extend(
N->getOperand(0));
18809 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
18810 unsigned Rev = VT == MVT::v4i32 ? ARMISD::VREV32 : ARMISD::VREV16;
18814 auto CheckInregMask = [&](
int Start,
int Offset) {
18816 if (Mask[Start + Idx] >= 0 && Mask[Start + Idx] != Idx * 2 +
Offset)
18822 if (CheckInregMask(0, 0))
18824 else if (CheckInregMask(0, 1))
18825 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18826 else if (CheckInregMask(0, Mask.size()))
18828 else if (CheckInregMask(0, Mask.size() + 1))
18829 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18834 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18838 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18845 if (
N->getOperand(0)->getOpcode() ==
ISD::LOAD)
18856 int NumOuts =
N->getNumValues();
18857 assert((NumOuts == 2 || NumOuts == 4) &&
18858 "Expected 2 or 4 outputs to an MVEEXT");
18859 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18861 if (
N->getNumOperands() == 4)
18867 StackPtr, MPI,
Align(4));
18870 for (
int I = 0;
I < NumOuts;
I++) {
18872 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18873 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
18878 VT, Chain, Ptr, MPI, LoadVT,
Align(4));
18887 switch (
N->getOpcode()) {
18947 case ARMISD::BRCOND:
18951 case ARMISD::CSINC:
18952 case ARMISD::CSINV:
18953 case ARMISD::CSNEG:
18966 case ARMISD::PREDICATE_CAST:
18968 case ARMISD::VECTOR_REG_CAST:
18979 case ARMISD::VADDVs:
18980 case ARMISD::VADDVu:
18981 case ARMISD::VADDLVs:
18982 case ARMISD::VADDLVu:
18983 case ARMISD::VADDLVAs:
18984 case ARMISD::VADDLVAu:
18985 case ARMISD::VMLAVs:
18986 case ARMISD::VMLAVu:
18987 case ARMISD::VMLALVs:
18988 case ARMISD::VMLALVu:
18989 case ARMISD::VMLALVAs:
18990 case ARMISD::VMLALVAu:
18992 case ARMISD::VMOVN:
18994 case ARMISD::VQMOVNs:
18995 case ARMISD::VQMOVNu:
18997 case ARMISD::VQDMULH:
19003 case ARMISD::SMULWB: {
19004 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19010 case ARMISD::SMULWT: {
19011 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19017 case ARMISD::SMLALBB:
19018 case ARMISD::QADD16b:
19019 case ARMISD::QSUB16b:
19020 case ARMISD::UQADD16b:
19021 case ARMISD::UQSUB16b: {
19022 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19029 case ARMISD::SMLALBT: {
19030 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
19032 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
19039 case ARMISD::SMLALTB: {
19040 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
19042 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
19049 case ARMISD::SMLALTT: {
19050 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19057 case ARMISD::QADD8b:
19058 case ARMISD::QSUB8b:
19059 case ARMISD::UQADD8b:
19060 case ARMISD::UQSUB8b: {
19061 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19069 if (
N->getOperand(1) ==
N->getOperand(2))
19070 return N->getOperand(1);
19074 switch (
N->getConstantOperandVal(1)) {
19075 case Intrinsic::arm_neon_vld1:
19076 case Intrinsic::arm_neon_vld1x2:
19077 case Intrinsic::arm_neon_vld1x3:
19078 case Intrinsic::arm_neon_vld1x4:
19079 case Intrinsic::arm_neon_vld2:
19080 case Intrinsic::arm_neon_vld3:
19081 case Intrinsic::arm_neon_vld4:
19082 case Intrinsic::arm_neon_vld2lane:
19083 case Intrinsic::arm_neon_vld3lane:
19084 case Intrinsic::arm_neon_vld4lane:
19085 case Intrinsic::arm_neon_vld2dup:
19086 case Intrinsic::arm_neon_vld3dup:
19087 case Intrinsic::arm_neon_vld4dup:
19088 case Intrinsic::arm_neon_vst1:
19089 case Intrinsic::arm_neon_vst1x2:
19090 case Intrinsic::arm_neon_vst1x3:
19091 case Intrinsic::arm_neon_vst1x4:
19092 case Intrinsic::arm_neon_vst2:
19093 case Intrinsic::arm_neon_vst3:
19094 case Intrinsic::arm_neon_vst4:
19095 case Intrinsic::arm_neon_vst2lane:
19096 case Intrinsic::arm_neon_vst3lane:
19097 case Intrinsic::arm_neon_vst4lane:
19099 case Intrinsic::arm_mve_vld2q:
19100 case Intrinsic::arm_mve_vld4q:
19101 case Intrinsic::arm_mve_vst2q:
19102 case Intrinsic::arm_mve_vst4q:
19119 unsigned *
Fast)
const {
19125 bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
19128 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
19130 if (AllowsUnaligned) {
19132 *
Fast = Subtarget->hasV7Ops();
19137 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
19141 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->isLittle())) {
19148 if (!Subtarget->hasMVEIntegerOps())
19152 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
19153 Ty == MVT::v2i1)) {
19161 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
19177 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
19178 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
19179 Ty == MVT::v2f64) {
19190 const AttributeList &FuncAttributes)
const {
19192 if ((
Op.isMemcpy() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
19193 !FuncAttributes.hasFnAttr(Attribute::NoImplicitFloat)) {
19195 if (
Op.size() >= 16 &&
19201 }
else if (
Op.size() >= 8 &&
19218 if (!SrcTy->isIntegerTy() || !DstTy->
isIntegerTy())
19220 unsigned SrcBits = SrcTy->getPrimitiveSizeInBits();
19222 return (SrcBits == 64 && DestBits == 32);
19231 return (SrcBits == 64 && DestBits == 32);
19267 return Subtarget->hasFullFP16();
19274 if (!Subtarget->hasMVEIntegerOps())
19293 if (Ld->isExpandingLoad())
19297 if (Subtarget->hasMVEIntegerOps())
19310 U->getOpcode() ==
ISD::SHL || U->getOpcode() == ARMISD::VSHLIMM))
19342bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19344 if (Subtarget->useSoftFloat())
19353 return Subtarget->hasMVEFloatOps();
19371 unsigned Scale = 1;
19388 if ((V & (Scale - 1)) != 0)
19397 if (VT.
isVector() && Subtarget->hasNEON())
19400 !Subtarget->hasMVEFloatOps())
19403 bool IsNeg =
false;
19409 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19412 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19428 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19434 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19464 default:
return false;
19483 int Scale = AM.
Scale;
19488 default:
return false;
19496 Scale = Scale & ~1;
19497 return Scale == 2 || Scale == 4 || Scale == 8;
19514 if (Scale & 1)
return false;
19521 const int Scale = AM.
Scale;
19531 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
19547 switch (AM.
Scale) {
19558 if (Subtarget->isThumb1Only())
19561 if (Subtarget->isThumb2())
19564 int Scale = AM.
Scale;
19566 default:
return false;
19570 if (Scale < 0) Scale = -Scale;
19578 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
19591 if (Scale & 1)
return false;
19604 if (!Subtarget->isThumb())
19607 if (Subtarget->isThumb2())
19611 return Imm >= 0 && Imm <= 255;
19621 if (!Subtarget->isThumb())
19623 if (Subtarget->isThumb2())
19626 return AbsImm <= 255;
19661 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
19665 int RHSC = (int)
RHS->getZExtValue();
19666 if (RHSC < 0 && RHSC > -256) {
19676 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
19679 int RHSC = (int)
RHS->getZExtValue();
19680 if (RHSC < 0 && RHSC > -0x1000) {
19722 int RHSC = (int)
RHS->getZExtValue();
19723 if (RHSC < 0 && RHSC > -0x100) {
19728 }
else if (RHSC > 0 && RHSC < 0x100) {
19739 bool isSEXTLoad,
bool IsMasked,
bool isLE,
19750 bool CanChangeType = isLE && !IsMasked;
19753 int RHSC = (int)
RHS->getZExtValue();
19755 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
19756 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
19761 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
19772 if (VT == MVT::v4i16) {
19773 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
19775 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
19776 if (IsInRange(RHSC, 0x80, 1))
19778 }
else if (Alignment >= 4 &&
19779 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
19780 IsInRange(RHSC, 0x80, 4))
19782 else if (Alignment >= 2 &&
19783 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
19784 IsInRange(RHSC, 0x80, 2))
19786 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
19799 if (Subtarget->isThumb1Only())
19806 bool isSEXTLoad =
false;
19807 bool IsMasked =
false;
19809 Ptr = LD->getBasePtr();
19810 VT = LD->getMemoryVT();
19811 Alignment = LD->getAlign();
19812 AS = LD->getAddressSpace();
19815 Ptr = ST->getBasePtr();
19816 VT = ST->getMemoryVT();
19817 Alignment = ST->getAlign();
19818 AS = ST->getAddressSpace();
19820 Ptr = LD->getBasePtr();
19821 VT = LD->getMemoryVT();
19822 Alignment = LD->getAlign();
19823 AS = LD->getAddressSpace();
19827 Ptr = ST->getBasePtr();
19828 VT = ST->getMemoryVT();
19829 Alignment = ST->getAlign();
19830 AS = ST->getAddressSpace();
19845 bool isLegal =
false;
19847 isLegal = Subtarget->hasMVEIntegerOps() &&
19849 Ptr.
getNode(), VT, Alignment, isSEXTLoad, IsMasked,
19850 Subtarget->isLittle(),
Base,
Offset, isInc, DAG);
19852 if (Subtarget->isThumb2())
19877 bool isSEXTLoad =
false, isNonExt;
19878 bool IsMasked =
false;
19880 VT = LD->getMemoryVT();
19881 Ptr = LD->getBasePtr();
19882 Alignment = LD->getAlign();
19886 VT = ST->getMemoryVT();
19887 Ptr = ST->getBasePtr();
19888 Alignment = ST->getAlign();
19889 isNonExt = !ST->isTruncatingStore();
19891 VT = LD->getMemoryVT();
19892 Ptr = LD->getBasePtr();
19893 Alignment = LD->getAlign();
19898 VT = ST->getMemoryVT();
19899 Ptr = ST->getBasePtr();
19900 Alignment = ST->getAlign();
19901 isNonExt = !ST->isTruncatingStore();
19906 if (Subtarget->isThumb1Only()) {
19909 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
19910 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
19913 if (!RHS || RHS->getZExtValue() != 4)
19915 if (Alignment <
Align(4))
19919 Base =
Op->getOperand(0);
19925 bool isLegal =
false;
19927 isLegal = Subtarget->hasMVEIntegerOps() &&
19932 if (Subtarget->isThumb2())
19946 !Subtarget->isThumb2())
19960 const APInt &DemandedElts,
19962 unsigned Depth)
const {
19965 switch (
Op.getOpcode()) {
19972 if (
Op.getResNo() == 0) {
19983 case ARMISD::CMOV: {
19998 case Intrinsic::arm_ldaex:
19999 case Intrinsic::arm_ldrex: {
20007 case ARMISD::BFI: {
20014 const APInt &Mask =
Op.getConstantOperandAPInt(2);
20015 Known.
Zero &= Mask;
20019 case ARMISD::VGETLANEs:
20020 case ARMISD::VGETLANEu: {
20021 const SDValue &SrcSV =
Op.getOperand(0);
20027 "VGETLANE index out of bounds");
20032 EVT VT =
Op.getValueType();
20038 if (
Op.getOpcode() == ARMISD::VGETLANEs)
20039 Known = Known.
sext(DstSz);
20041 Known = Known.
zext(DstSz);
20046 case ARMISD::VMOVrh: {
20049 Known = KnownOp.
zext(32);
20052 case ARMISD::CSINC:
20053 case ARMISD::CSINV:
20054 case ARMISD::CSNEG: {
20062 if (
Op.getOpcode() == ARMISD::CSINC)
20065 else if (
Op.getOpcode() == ARMISD::CSINV)
20067 else if (
Op.getOpcode() == ARMISD::CSNEG)
20074 case ARMISD::VORRIMM:
20075 case ARMISD::VBICIMM: {
20076 unsigned Encoded =
Op.getConstantOperandVal(1);
20077 unsigned DecEltBits = 0;
20080 unsigned EltBits =
Op.getScalarValueSizeInBits();
20081 if (EltBits != DecEltBits) {
20090 bool IsVORR =
Op.getOpcode() == ARMISD::VORRIMM;
20091 APInt Imm(DecEltBits, DecodedVal);
20093 Known.
One = IsVORR ? (KnownLHS.
One | Imm) : (KnownLHS.
One & ~Imm);
20094 Known.
Zero = IsVORR ? (KnownLHS.
Zero & ~Imm) : (KnownLHS.
Zero | Imm);
20112 EVT VT =
Op.getValueType();
20118 assert(VT == MVT::i32 &&
"Unexpected integer type");
20125 unsigned Mask =
C->getZExtValue();
20128 unsigned ShrunkMask = Mask & Demanded;
20129 unsigned ExpandedMask = Mask | ~Demanded;
20133 if (ShrunkMask == 0)
20139 if (ExpandedMask == ~0U)
20142 auto IsLegalMask = [ShrunkMask, ExpandedMask](
unsigned Mask) ->
bool {
20143 return (ShrunkMask & Mask) == ShrunkMask && (~ExpandedMask & Mask) == 0;
20145 auto UseMask = [Mask,
Op, VT, &TLO](
unsigned NewMask) ->
bool {
20146 if (NewMask == Mask)
20155 if (IsLegalMask(0xFF))
20156 return UseMask(0xFF);
20159 if (IsLegalMask(0xFFFF))
20160 return UseMask(0xFFFF);
20164 if (ShrunkMask < 256)
20165 return UseMask(ShrunkMask);
20169 if ((
int)ExpandedMask <= -2 && (
int)ExpandedMask >= -256)
20170 return UseMask(ExpandedMask);
20185 unsigned Depth)
const {
20186 unsigned Opc =
Op.getOpcode();
20190 case ARMISD::LSRL: {
20194 if (
Op.getResNo() == 0 && !
Op->hasAnyUseOfValue(1) &&
20196 unsigned ShAmt =
Op->getConstantOperandVal(2);
20206 case ARMISD::VBICIMM: {
20208 unsigned ModImm =
Op.getConstantOperandVal(1);
20209 unsigned EltBits = 0;
20211 if ((OriginalDemandedBits & Mask) == 0)
20217 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
20232 if (!Subtarget->hasVFP2Base())
20236 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20248 unsigned S = Constraint.
size();
20250 switch (Constraint[0]) {
20262 }
else if (S == 2) {
20263 switch (Constraint[0]) {
20280 Value *CallOperandVal =
info.CallOperandVal;
20283 if (!CallOperandVal)
20287 switch (*constraint) {
20293 if (Subtarget->isThumb())
20308 if (PR == 0 || VT == MVT::Other)
20310 if (ARM::SPRRegClass.
contains(PR))
20311 return VT != MVT::f32 && VT != MVT::f16 && VT != MVT::i32;
20312 if (ARM::DPRRegClass.
contains(PR))
20317using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20321 switch (Constraint.
size()) {
20324 switch (Constraint[0]) {
20326 if (Subtarget->isThumb())
20327 return RCPair(0U, &ARM::tGPRRegClass);
20328 return RCPair(0U, &ARM::GPRRegClass);
20330 if (Subtarget->isThumb())
20331 return RCPair(0U, &ARM::hGPRRegClass);
20334 if (Subtarget->isThumb1Only())
20335 return RCPair(0U, &ARM::tGPRRegClass);
20336 return RCPair(0U, &ARM::GPRRegClass);
20338 if (VT == MVT::Other)
20340 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20341 return RCPair(0U, &ARM::SPRRegClass);
20343 return RCPair(0U, &ARM::DPRRegClass);
20345 return RCPair(0U, &ARM::QPRRegClass);
20348 if (VT == MVT::Other)
20350 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20351 return RCPair(0U, &ARM::SPR_8RegClass);
20353 return RCPair(0U, &ARM::DPR_8RegClass);
20355 return RCPair(0U, &ARM::QPR_8RegClass);
20358 if (VT == MVT::Other)
20360 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20361 return RCPair(0U, &ARM::SPRRegClass);
20363 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20365 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20371 if (Constraint[0] ==
'T') {
20372 switch (Constraint[1]) {
20376 return RCPair(0U, &ARM::tGPREvenRegClass);
20378 return RCPair(0U, &ARM::tGPROddRegClass);
20387 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20388 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20391 if (
StringRef(
"{r14}").equals_insensitive(Constraint))
20392 return std::make_pair(
unsigned(ARM::LR),
getRegClassFor(MVT::i32));
20396 return {0,
nullptr};
20404 std::vector<SDValue> &
Ops,
20409 if (Constraint.
size() != 1)
20412 char ConstraintLetter = Constraint[0];
20413 switch (ConstraintLetter) {
20416 case 'I':
case 'J':
case 'K':
case 'L':
20417 case 'M':
case 'N':
case 'O':
20422 int64_t CVal64 =
C->getSExtValue();
20423 int CVal = (int) CVal64;
20426 if (CVal != CVal64)
20429 switch (ConstraintLetter) {
20433 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
20434 if (CVal >= 0 && CVal <= 65535)
20438 if (Subtarget->isThumb1Only()) {
20441 if (CVal >= 0 && CVal <= 255)
20443 }
else if (Subtarget->isThumb2()) {
20457 if (Subtarget->isThumb1Only()) {
20462 if (CVal >= -255 && CVal <= -1)
20468 if (CVal >= -4095 && CVal <= 4095)
20474 if (Subtarget->isThumb1Only()) {
20481 }
else if (Subtarget->isThumb2()) {
20501 if (Subtarget->isThumb1Only()) {
20504 if (CVal >= -7 && CVal < 7)
20506 }
else if (Subtarget->isThumb2()) {
20526 if (Subtarget->isThumb1Only()) {
20529 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
20535 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
20541 if (Subtarget->isThumb1Only()) {
20543 if (CVal >= 0 && CVal <= 31)
20549 if (Subtarget->isThumb1Only()) {
20552 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
20561 if (Result.getNode()) {
20562 Ops.push_back(Result);
20572 "Unhandled Opcode in getDivRemLibcall");
20578 case MVT::i8: LC = isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
20579 case MVT::i16: LC = isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
20580 case MVT::i32: LC = isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
20581 case MVT::i64: LC = isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
20590 "Unhandled Opcode in getDivRemArgList");
20594 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
20595 EVT ArgVT =
N->getOperand(i).getValueType();
20598 Entry.IsSExt = isSigned;
20599 Entry.IsZExt = !isSigned;
20600 Args.push_back(Entry);
20608 assert((Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() ||
20609 Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() ||
20610 Subtarget->isTargetFuchsia() || Subtarget->isTargetWindows()) &&
20611 "Register-based DivRem lowering only");
20612 unsigned Opcode =
Op->getOpcode();
20614 "Invalid opcode for Div/Rem lowering");
20616 EVT VT =
Op->getValueType(0);
20638 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
20639 : Subtarget->hasDivideInARMMode();
20640 if (hasDivide &&
Op->getValueType(0).isSimple() &&
20641 Op->getSimpleValueType(0) == MVT::i32) {
20643 const SDValue Dividend =
Op->getOperand(0);
20644 const SDValue Divisor =
Op->getOperand(1);
20645 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
20649 SDValue Values[2] = {Div, Rem};
20668 if (
getTM().getTargetTriple().isOSWindows())
20671 TargetLowering::CallLoweringInfo CLI(DAG);
20675 Callee, std::move(Args))
20680 std::pair<SDValue, SDValue> CallInfo =
LowerCallTo(CLI);
20681 return CallInfo.first;
20687 EVT VT =
N->getValueType(0);
20693 Result[0], Result[1]);
20697 std::vector<Type*> RetTyParams;
20698 Type *RetTyElement;
20708 RetTyParams.push_back(RetTyElement);
20709 RetTyParams.push_back(RetTyElement);
20719 bool isSigned =
N->getOpcode() ==
ISD::SREM;
20724 if (
getTM().getTargetTriple().isOSWindows())
20731 Callee, std::move(Args))
20735 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
20738 SDNode *ResNode = CallResult.first.getNode();
20745 assert(
getTM().getTargetTriple().isOSWindows() &&
20746 "unsupported target platform");
20754 "no-stack-arg-probe")) {
20758 Chain =
SP.getValue(1);
20775 SDVTList NodeTys = DAG.
getVTList(MVT::Other, MVT::Glue);
20776 Chain = DAG.
getNode(ARMISD::WIN__CHKSTK,
DL, NodeTys, Chain, Glue);
20786 bool IsStrict =
Op->isStrictFPOpcode();
20787 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20788 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20790 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
20791 "Unexpected type for custom-lowering FP_EXTEND");
20793 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20794 "With both FP DP and 16, any FP conversion is legal!");
20796 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
20797 "With FP16, 16 to 32 conversion is legal!");
20800 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
20805 Loc,
Op.getValueType(), SrcVal);
20820 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
20821 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
20822 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
20823 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
20827 {DstVT, MVT::Other}, {Chain, SrcVal});
20834 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20835 "Unexpected type for custom-lowering FP_EXTEND");
20836 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20841 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
20845 bool IsStrict =
Op->isStrictFPOpcode();
20847 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20849 EVT DstVT =
Op.getValueType();
20850 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20853 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
20854 "Unexpected type for custom-lowering FP_ROUND");
20856 assert((!Subtarget->hasFP64() || !Subtarget->hasFPARMv8Base()) &&
20857 "With both FP DP and 16, any FP conversion is legal!");
20862 if (SrcSz == 32 && Subtarget->hasFP16())
20867 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20868 "Unexpected type for custom-lowering FP_ROUND");
20872 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20884 if (v == 0xffffffff)
20896 bool ForCodeSize)
const {
20897 if (!Subtarget->hasVFP3Base())
20899 if (VT == MVT::f16 && Subtarget->hasFullFP16())
20901 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
20904 if (VT == MVT::f32)
20906 if (VT == MVT::f64 && Subtarget->hasFP64())
20919 case Intrinsic::arm_neon_vld1:
20920 case Intrinsic::arm_neon_vld2:
20921 case Intrinsic::arm_neon_vld3:
20922 case Intrinsic::arm_neon_vld4:
20923 case Intrinsic::arm_neon_vld2lane:
20924 case Intrinsic::arm_neon_vld3lane:
20925 case Intrinsic::arm_neon_vld4lane:
20926 case Intrinsic::arm_neon_vld2dup:
20927 case Intrinsic::arm_neon_vld3dup:
20928 case Intrinsic::arm_neon_vld4dup: {
20931 auto &
DL =
I.getDataLayout();
20932 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20934 Info.ptrVal =
I.getArgOperand(0);
20936 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20943 case Intrinsic::arm_neon_vld1x2:
20944 case Intrinsic::arm_neon_vld1x3:
20945 case Intrinsic::arm_neon_vld1x4: {
20948 auto &
DL =
I.getDataLayout();
20949 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20951 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
20953 Info.align =
I.getParamAlign(
I.arg_size() - 1).valueOrOne();
20959 case Intrinsic::arm_neon_vst1:
20960 case Intrinsic::arm_neon_vst2:
20961 case Intrinsic::arm_neon_vst3:
20962 case Intrinsic::arm_neon_vst4:
20963 case Intrinsic::arm_neon_vst2lane:
20964 case Intrinsic::arm_neon_vst3lane:
20965 case Intrinsic::arm_neon_vst4lane: {
20968 auto &
DL =
I.getDataLayout();
20969 unsigned NumElts = 0;
20970 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20971 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20974 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
20977 Info.ptrVal =
I.getArgOperand(0);
20979 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20986 case Intrinsic::arm_neon_vst1x2:
20987 case Intrinsic::arm_neon_vst1x3:
20988 case Intrinsic::arm_neon_vst1x4: {
20991 auto &
DL =
I.getDataLayout();
20992 unsigned NumElts = 0;
20993 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20994 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20997 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21000 Info.ptrVal =
I.getArgOperand(0);
21002 Info.align =
I.getParamAlign(0).valueOrOne();
21008 case Intrinsic::arm_mve_vld2q:
21009 case Intrinsic::arm_mve_vld4q: {
21013 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
21015 Info.ptrVal =
I.getArgOperand(0);
21023 case Intrinsic::arm_mve_vst2q:
21024 case Intrinsic::arm_mve_vst4q: {
21027 Type *VecTy =
I.getArgOperand(1)->getType();
21028 unsigned Factor =
Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
21030 Info.ptrVal =
I.getArgOperand(0);
21038 case Intrinsic::arm_mve_vldr_gather_base:
21039 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
21041 Info.ptrVal =
nullptr;
21043 Info.align =
Align(1);
21048 case Intrinsic::arm_mve_vldr_gather_base_wb:
21049 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
21051 Info.ptrVal =
nullptr;
21052 Info.memVT =
MVT::getVT(
I.getType()->getContainedType(0));
21053 Info.align =
Align(1);
21058 case Intrinsic::arm_mve_vldr_gather_offset:
21059 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
21061 Info.ptrVal =
nullptr;
21066 Info.align =
Align(1);
21071 case Intrinsic::arm_mve_vstr_scatter_base:
21072 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
21074 Info.ptrVal =
nullptr;
21075 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21076 Info.align =
Align(1);
21081 case Intrinsic::arm_mve_vstr_scatter_base_wb:
21082 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
21084 Info.ptrVal =
nullptr;
21085 Info.memVT =
MVT::getVT(
I.getArgOperand(2)->getType());
21086 Info.align =
Align(1);
21091 case Intrinsic::arm_mve_vstr_scatter_offset:
21092 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
21094 Info.ptrVal =
nullptr;
21099 Info.align =
Align(1);
21104 case Intrinsic::arm_ldaex:
21105 case Intrinsic::arm_ldrex: {
21106 auto &
DL =
I.getDataLayout();
21107 Type *ValTy =
I.getParamElementType(0);
21110 Info.ptrVal =
I.getArgOperand(0);
21112 Info.align =
DL.getABITypeAlign(ValTy);
21117 case Intrinsic::arm_stlex:
21118 case Intrinsic::arm_strex: {
21119 auto &
DL =
I.getDataLayout();
21120 Type *ValTy =
I.getParamElementType(1);
21123 Info.ptrVal =
I.getArgOperand(1);
21125 Info.align =
DL.getABITypeAlign(ValTy);
21130 case Intrinsic::arm_stlexd:
21131 case Intrinsic::arm_strexd:
21133 Info.memVT = MVT::i64;
21134 Info.ptrVal =
I.getArgOperand(2);
21136 Info.align =
Align(8);
21141 case Intrinsic::arm_ldaexd:
21142 case Intrinsic::arm_ldrexd:
21144 Info.memVT = MVT::i64;
21145 Info.ptrVal =
I.getArgOperand(0);
21147 Info.align =
Align(8);
21161 assert(Ty->isIntegerTy());
21163 unsigned Bits = Ty->getPrimitiveSizeInBits();
21164 if (Bits == 0 || Bits > 32)
21170 unsigned Index)
const {
21180 if (!Subtarget->hasDataBarrier()) {
21184 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
21185 Value*
args[6] = {Builder.getInt32(15), Builder.getInt32(0),
21186 Builder.getInt32(0), Builder.getInt32(7),
21187 Builder.getInt32(10), Builder.getInt32(5)};
21188 return Builder.CreateIntrinsic(Intrinsic::arm_mcr,
args);
21198 return Builder.CreateIntrinsic(Intrinsic::arm_dmb, CDomain);
21219 if (Subtarget->preferISHSTBarriers())
21252 bool has64BitAtomicStore;
21253 if (Subtarget->isMClass())
21254 has64BitAtomicStore =
false;
21255 else if (Subtarget->isThumb())
21256 has64BitAtomicStore = Subtarget->hasV7Ops();
21258 has64BitAtomicStore = Subtarget->hasV6Ops();
21260 unsigned Size =
SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21274 bool has64BitAtomicLoad;
21275 if (Subtarget->isMClass())
21276 has64BitAtomicLoad =
false;
21277 else if (Subtarget->isThumb())
21278 has64BitAtomicLoad = Subtarget->hasV7Ops();
21280 has64BitAtomicLoad = Subtarget->hasV6Ops();
21296 if (Subtarget->isMClass())
21297 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21298 else if (Subtarget->isThumb())
21299 hasAtomicRMW = Subtarget->hasV7Ops();
21301 hasAtomicRMW = Subtarget->hasV6Ops();
21302 if (
Size <= (Subtarget->isMClass() ? 32U : 64U) && hasAtomicRMW) {
21326 bool HasAtomicCmpXchg;
21327 if (Subtarget->isMClass())
21328 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21329 else if (Subtarget->isThumb())
21330 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21332 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21334 HasAtomicCmpXchg &&
Size <= (Subtarget->isMClass() ? 32U : 64U))
21341 return InsertFencesForAtomic;
21346 return !Subtarget->isROPI() && !Subtarget->isRWPI();
21352 RTLIB::LibcallImpl SecurityCheckCookieLibcall =
21353 Libcalls.getLibcallImpl(RTLIB::SECURITY_CHECK_COOKIE);
21355 RTLIB::LibcallImpl SecurityCookieVar =
21356 Libcalls.getLibcallImpl(RTLIB::STACK_CHECK_GUARD);
21357 if (SecurityCheckCookieLibcall != RTLIB::Unsupported &&
21358 SecurityCookieVar != RTLIB::Unsupported) {
21369 F->addParamAttr(0, Attribute::AttrKind::InReg);
21376 unsigned &
Cost)
const {
21378 if (!Subtarget->hasNEON())
21407 unsigned Opcode =
Op.getOpcode();
21409 case ARMISD::VORRIMM:
21410 case ARMISD::VBICIMM:
21418 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21422 return Subtarget->hasV5TOps() && !Subtarget->isThumb1Only();
21427 if (!Subtarget->hasV7Ops())
21433 if (!Mask || Mask->getValue().getBitWidth() > 32u)
21435 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
21443 if (Subtarget->hasMinSize() && !
getTM().getTargetTriple().isOSWindows())
21452 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21458 if (ValueTy->getPrimitiveSizeInBits() == 64) {
21460 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
21463 Builder.CreateIntrinsic(
Int, Addr,
nullptr,
"lohi");
21465 Value *
Lo = Builder.CreateExtractValue(LoHi, 0,
"lo");
21466 Value *
Hi = Builder.CreateExtractValue(LoHi, 1,
"hi");
21467 if (!Subtarget->isLittle())
21469 Lo = Builder.CreateZExt(
Lo, ValueTy,
"lo64");
21470 Hi = Builder.CreateZExt(
Hi, ValueTy,
"hi64");
21471 return Builder.CreateOr(
21472 Lo, Builder.CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
21476 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
21477 CallInst *CI = Builder.CreateIntrinsic(
Int, Tys, Addr);
21480 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
21481 return Builder.CreateTruncOrBitCast(CI, ValueTy);
21486 if (!Subtarget->hasV7Ops())
21488 Builder.CreateIntrinsic(Intrinsic::arm_clrex, {});
21494 Module *M = Builder.GetInsertBlock()->getParent()->getParent();
21502 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
21506 Value *
Hi = Builder.CreateTrunc(Builder.CreateLShr(Val, 32),
Int32Ty,
"hi");
21507 if (!Subtarget->isLittle())
21509 return Builder.CreateIntrinsic(
Int, {
Lo,
Hi, Addr});
21512 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
21516 CallInst *CI = Builder.CreateCall(
21517 Strex, {Builder.CreateZExtOrBitCast(
21527 return Subtarget->isMClass();
21535 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
21542 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
21545 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
21553 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
21561 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
21564 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
21569 if (Subtarget->hasNEON() && VecSize == 64)
21571 return VecSize % 128 == 0;
21575 if (Subtarget->hasNEON())
21577 if (Subtarget->hasMVEIntegerOps())
21597 "Invalid interleave factor");
21598 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
21600 "Unmatched number of shufflevectors and indices");
21605 assert(!Mask && GapMask.
popcount() == Factor &&
"Unexpected mask on a load");
21608 Type *EltTy = VecTy->getElementType();
21611 Align Alignment = LI->getAlign();
21629 Value *BaseAddr = LI->getPointerOperand();
21631 if (NumLoads > 1) {
21635 VecTy->getNumElements() / NumLoads);
21641 if (Subtarget->hasNEON()) {
21642 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21643 Type *Tys[] = {VecTy, PtrTy};
21644 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
21645 Intrinsic::arm_neon_vld3,
21646 Intrinsic::arm_neon_vld4};
21649 Ops.push_back(BaseAddr);
21650 Ops.push_back(Builder.getInt32(LI->getAlign().value()));
21652 return Builder.CreateIntrinsic(LoadInts[Factor - 2], Tys,
Ops,
21655 assert((Factor == 2 || Factor == 4) &&
21656 "expected interleave factor of 2 or 4 for MVE");
21658 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
21659 Type *PtrTy = Builder.getPtrTy(LI->getPointerAddressSpace());
21660 Type *Tys[] = {VecTy, PtrTy};
21663 Ops.push_back(BaseAddr);
21664 return Builder.CreateIntrinsic(LoadInts, Tys,
Ops,
nullptr,
21674 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
21678 BaseAddr = Builder.CreateConstGEP1_32(VecTy->getElementType(), BaseAddr,
21679 VecTy->getNumElements() * Factor);
21685 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
21687 unsigned Index = Indices[i];
21689 Value *SubVec = Builder.CreateExtractValue(VldN, Index);
21693 SubVec = Builder.CreateIntToPtr(
21697 SubVecs[SV].push_back(SubVec);
21706 auto &SubVec = SubVecs[SVI];
21709 SVI->replaceAllUsesWith(WideVec);
21745 const APInt &GapMask)
const {
21747 "Invalid interleave factor");
21752 "Unexpected mask on store");
21755 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
21757 unsigned LaneLen = VecTy->getNumElements() / Factor;
21758 Type *EltTy = VecTy->getElementType();
21762 Align Alignment =
SI->getAlign();
21779 Type *IntTy =
DL.getIntPtrType(EltTy);
21784 Op0 = Builder.CreatePtrToInt(Op0, IntVecTy);
21785 Op1 = Builder.CreatePtrToInt(Op1, IntVecTy);
21791 Value *BaseAddr =
SI->getPointerOperand();
21793 if (NumStores > 1) {
21796 LaneLen /= NumStores;
21806 if (Subtarget->hasNEON()) {
21807 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
21808 Intrinsic::arm_neon_vst3,
21809 Intrinsic::arm_neon_vst4};
21810 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21811 Type *Tys[] = {PtrTy, SubVecTy};
21814 Ops.push_back(BaseAddr);
21816 Ops.push_back(Builder.getInt32(
SI->getAlign().value()));
21817 Builder.CreateIntrinsic(StoreInts[Factor - 2], Tys,
Ops);
21819 assert((Factor == 2 || Factor == 4) &&
21820 "expected interleave factor of 2 or 4 for MVE");
21822 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
21823 Type *PtrTy = Builder.getPtrTy(
SI->getPointerAddressSpace());
21824 Type *Tys[] = {PtrTy, SubVecTy};
21827 Ops.push_back(BaseAddr);
21829 for (
unsigned F = 0;
F < Factor;
F++) {
21830 Ops.push_back(Builder.getInt32(
F));
21831 Builder.CreateIntrinsic(StoreInts, Tys,
Ops);
21837 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
21840 if (StoreCount > 0)
21841 BaseAddr = Builder.CreateConstGEP1_32(SubVecTy->getElementType(),
21842 BaseAddr, LaneLen * Factor);
21847 for (
unsigned i = 0; i < Factor; i++) {
21848 unsigned IdxI = StoreCount * LaneLen * Factor + i;
21849 if (Mask[IdxI] >= 0) {
21850 Shuffles.
push_back(Builder.CreateShuffleVector(
21853 unsigned StartMask = 0;
21854 for (
unsigned j = 1; j < LaneLen; j++) {
21855 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
21856 if (Mask[IdxJ * Factor + IdxI] >= 0) {
21857 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
21867 Shuffles.
push_back(Builder.CreateShuffleVector(
21888 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
21892 Members += SubMembers;
21898 Members += SubMembers * AT->getNumElements();
21899 }
else if (Ty->isFloatTy()) {
21904 }
else if (Ty->isDoubleTy()) {
21916 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
21918 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
21920 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
21933 return (Members > 0 && Members <= 4);
21939 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
21941 return ABITypeAlign;
21946 assert(StackAlign &&
"data layout string is missing stack alignment");
21947 return std::min(ABITypeAlign, *StackAlign);
21956 if (getEffectiveCallingConv(CallConv, isVarArg) !=
21965 bool IsIntArray = Ty->isArrayTy() && Ty->getArrayElementType()->isIntegerTy();
21966 return IsHA || IsIntArray;
21970 const Constant *PersonalityFn)
const {
21978 const Constant *PersonalityFn)
const {
21991void ARMTargetLowering::insertCopiesSplitCSR(
21995 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
22005 RC = &ARM::GPRRegClass;
22006 else if (ARM::DPRRegClass.
contains(*
I))
22007 RC = &ARM::DPRRegClass;
22017 assert(Entry->getParent()->getFunction().hasFnAttribute(
22018 Attribute::NoUnwind) &&
22019 "Function should be nounwind in insertCopiesSplitCSR!");
22020 Entry->addLiveIn(*
I);
22025 for (
auto *Exit : Exits)
22027 TII->get(TargetOpcode::COPY), *
I)
22038 return Subtarget->hasMVEIntegerOps();
22048 unsigned NumElements = VTy->getNumElements();
22055 if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy())
22056 return Subtarget->hasMVEFloatOps();
22061 return Subtarget->hasMVEIntegerOps() &&
22062 (ScalarTy->isIntegerTy(8) || ScalarTy->isIntegerTy(16) ||
22063 ScalarTy->isIntegerTy(32));
22067 static const MCPhysReg RCRegs[] = {ARM::FPSCR_RM};
22078 unsigned TyWidth = Ty->getScalarSizeInBits() * Ty->getNumElements();
22080 assert(TyWidth >= 128 &&
"Width of vector type must be at least 128 bits");
22082 if (TyWidth > 128) {
22083 int Stride = Ty->getNumElements() / 2;
22087 ArrayRef<int> UpperSplitMask(&SplitSeqVec[Stride], Stride);
22089 auto *LowerSplitA =
B.CreateShuffleVector(InputA, LowerSplitMask);
22090 auto *LowerSplitB =
B.CreateShuffleVector(InputB, LowerSplitMask);
22091 auto *UpperSplitA =
B.CreateShuffleVector(InputA, UpperSplitMask);
22092 auto *UpperSplitB =
B.CreateShuffleVector(InputB, UpperSplitMask);
22093 Value *LowerSplitAcc =
nullptr;
22094 Value *UpperSplitAcc =
nullptr;
22097 LowerSplitAcc =
B.CreateShuffleVector(
Accumulator, LowerSplitMask);
22098 UpperSplitAcc =
B.CreateShuffleVector(
Accumulator, UpperSplitMask);
22102 B, OperationType, Rotation, LowerSplitA, LowerSplitB, LowerSplitAcc);
22104 B, OperationType, Rotation, UpperSplitA, UpperSplitB, UpperSplitAcc);
22106 ArrayRef<int> JoinMask(&SplitSeqVec[0], Ty->getNumElements());
22107 return B.CreateShuffleVector(LowerSplitInt, UpperSplitInt, JoinMask);
22114 ConstRotation = ConstantInt::get(IntTy, (
int)Rotation);
22117 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmlaq, Ty,
22119 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmulq, Ty,
22120 {ConstRotation, InputB, InputA});
22125 auto *ConstHalving = ConstantInt::get(IntTy, 1);
22128 ConstRotation = ConstantInt::get(IntTy, 0);
22130 ConstRotation = ConstantInt::get(IntTy, 1);
22132 if (!ConstRotation)
22135 return B.CreateIntrinsic(Intrinsic::arm_mve_vcaddq, Ty,
22136 {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 bool isZeroExtended(SDValue N, SelectionDAG &DAG)
static const MCPhysReg GPRArgRegs[]
static SDValue GeneratePerfectShuffle(unsigned ID, SDValue V1, SDValue V2, unsigned PFEntry, SDValue LHS, SDValue RHS, SelectionDAG &DAG, const SDLoc &DL)
GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit the specified operations t...
constexpr MVT FlagsVT
Value type used for NZCV flags.
static bool getVShiftImm(SDValue Op, unsigned ElementBits, int64_t &Cnt)
getVShiftImm - Check if this is a valid build_vector for the immediate operand of a vector shift oper...
static SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG)
static bool isSignExtended(SDValue N, SelectionDAG &DAG)
static bool isAddSubZExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftLImm(SDValue Op, EVT VT, bool isLong, int64_t &Cnt)
isVShiftLImm - Check if this is a valid build_vector for the immediate operand of a vector shift left...
static bool canGuaranteeTCO(CallingConv::ID CC, bool GuaranteeTailCalls)
Return true if the calling convention is one that we can guarantee TCO for.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
static bool isConstant(const MachineInstr &MI)
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG)
static bool isStore(int Opcode)
static bool isThumb(const MCSubtargetInfo &STI)
static SDValue LowerUADDSUBO_CARRY(SDValue Op, SelectionDAG &DAG)
static SDValue PerformExtractEltToVMOVRRD(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isIncompatibleReg(const MCPhysReg &PR, MVT VT)
static SDValue PerformVQDMULHCombine(SDNode *N, SelectionDAG &DAG)
static SDValue LowerBUILD_VECTOR_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerShift(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue AddRequiredExtensionForVMULL(SDValue N, SelectionDAG &DAG, const EVT &OrigTy, const EVT &ExtTy, unsigned ExtOpcode)
AddRequiredExtensionForVMULL - Add a sign/zero extension to extend the total value size to 64 bits.
static cl::opt< unsigned > ConstpoolPromotionMaxSize("arm-promote-constant-max-size", cl::Hidden, cl::desc("Maximum size of constant to promote into a constant pool"), cl::init(64))
static bool isZeroOrAllOnes(SDValue N, bool AllOnes)
static SDValue LowerINSERT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isVTBLMask(ArrayRef< int > M, EVT VT)
static SDValue PerformSUBCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSUBCombine - Target-specific dag combine xforms for ISD::SUB.
static cl::opt< bool > EnableConstpoolPromotion("arm-promote-constant", cl::Hidden, cl::desc("Enable / disable promotion of unnamed_addr constants into " "constant pools"), cl::init(false))
static SDValue PerformFAddVSelectCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformExtractFpToIntStores(StoreSDNode *St, SelectionDAG &DAG)
static SDValue PerformVDUPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVDUPCombine - Target-specific dag combine xforms for ARMISD::VDUP.
static SDValue PerformExtractEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static const APInt * isPowerOf2Constant(SDValue V)
static SDValue PerformVCVTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVCVTCombine - VCVT (floating-point to fixed-point, Advanced SIMD) can replace combinations of ...
static SDValue PerformVMOVhrCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorFP_TO_INT(SDValue Op, SelectionDAG &DAG)
static SDValue LowerVECTOR_SHUFFLEUsingOneOff(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static bool isValidMVECond(unsigned CC, bool IsFloat)
static SDValue PerformPREDICATE_CASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static ARMCC::CondCodes IntCCToARMCC(ISD::CondCode CC)
IntCCToARMCC - Convert a DAG integer condition code to an ARM CC.
static SDValue PerformSTORECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformSTORECombine - Target-specific dag combine xforms for ISD::STORE.
static SDValue ConvertBooleanCarryToCarryFlag(SDValue BoolCarry, SelectionDAG &DAG)
static SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isGTorGE(ISD::CondCode CC)
static bool CombineVLDDUP(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineVLDDUP - For a VDUPLANE node N, check if its source operand is a vldN-lane (N > 1) intrinsic,...
static SDValue ParseBFI(SDNode *N, APInt &ToMask, APInt &FromMask)
static bool isReverseMask(ArrayRef< int > M, EVT VT)
static bool isVZIP_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVZIP_v_undef_Mask - Special case of isVZIPMask for canonical form of "vector_shuffle v,...
static SDValue PerformSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue AddCombineTo64bitUMAAL(SDNode *AddeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVECTOR_REG_CASTCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVMulVCTPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
PerformVMulVCTPCombine - VCVT (fixed-point to floating-point, Advanced SIMD) can replace combinations...
static SDValue createGPRPairNode2xi32(SelectionDAG &DAG, SDValue V0, SDValue V1)
static SDValue bitcastf32Toi32(SDValue Op, SelectionDAG &DAG)
static bool findPointerConstIncrement(SDNode *N, SDValue *Ptr, SDValue *CInc)
static bool isVTRNMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue LowerEXTRACT_SUBVECTOR(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool CanInvertMVEVCMP(SDValue N)
static SDValue PerformLongShiftCombine(SDNode *N, SelectionDAG &DAG)
static SDValue AddCombineToVPADD(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformShiftCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
PerformShiftCombine - Checks for immediate versions of vector shifts and lowers them.
static void FPCCToARMCC(ISD::CondCode CC, ARMCC::CondCodes &CondCode, ARMCC::CondCodes &CondCode2)
FPCCToARMCC - Convert a DAG fp condition code to an ARM CC.
static void ExpandREAD_REGISTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static EVT getVectorTyFromPredicateVector(EVT VT)
static SDValue PerformFADDVCMLACombine(SDNode *N, SelectionDAG &DAG)
static SDValue handleCMSEValue(const SDValue &Value, const ISD::InputArg &Arg, SelectionDAG &DAG, const SDLoc &DL)
static SDValue PerformARMBUILD_VECTORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
Target-specific dag combine xforms for ARMISD::BUILD_VECTOR.
static bool isSRL16(const SDValue &Op)
static SDValue PerformVMOVrhCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformLOADCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue IsCMPZCSINC(SDNode *Cmp, ARMCC::CondCodes &CC)
static unsigned getPointerConstIncrement(unsigned Opcode, SDValue Ptr, SDValue Inc, const SelectionDAG &DAG)
static SDValue combineSelectAndUseCommutative(SDNode *N, bool AllOnes, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static Register genTPEntry(MachineBasicBlock *TpEntry, MachineBasicBlock *TpLoopBody, MachineBasicBlock *TpExit, Register OpSizeReg, const TargetInstrInfo *TII, DebugLoc Dl, MachineRegisterInfo &MRI)
Adds logic in loop entry MBB to calculate loop iteration count and adds t2WhileLoopSetup and t2WhileL...
static SDValue createGPRPairNodei64(SelectionDAG &DAG, SDValue V)
static bool isLTorLE(ISD::CondCode CC)
static SDValue PerformVCMPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformMVEVMULLCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerSDIV_v4i16(SDValue N0, SDValue N1, const SDLoc &dl, SelectionDAG &DAG)
static SDValue performNegCMovCombine(SDNode *N, SelectionDAG &DAG)
static EVT getExtensionTo64Bits(const EVT &OrigVT)
static SDValue PerformBITCASTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue AddCombineTo64bitMLAL(SDNode *AddeSubeNode, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG)
static bool checkAndUpdateCPSRKill(MachineBasicBlock::iterator SelectItr, MachineBasicBlock *BB, const TargetRegisterInfo *TRI)
static SDValue PerformCMPZCombine(SDNode *N, SelectionDAG &DAG)
static bool hasNormalLoadOperand(SDNode *N)
hasNormalLoadOperand - Check if any of the operands of a BUILD_VECTOR node are normal,...
static SDValue PerformInsertEltCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
PerformInsertEltCombine - Target-specific dag combine xforms for ISD::INSERT_VECTOR_ELT.
static SDValue PerformVDUPLANECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVDUPLANECombine - Target-specific dag combine xforms for ARMISD::VDUPLANE.
static SDValue LowerBuildVectorOfFPTrunc(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static cl::opt< unsigned > ConstpoolPromotionMaxTotal("arm-promote-constant-max-total", cl::Hidden, cl::desc("Maximum size of ALL constants to promote into a constant pool"), cl::init(128))
static SDValue LowerTruncatei1(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static RTLIB::Libcall getDivRemLibcall(const SDNode *N, MVT::SimpleValueType SVT)
static SDValue SkipLoadExtensionForVMULL(LoadSDNode *LD, SelectionDAG &DAG)
SkipLoadExtensionForVMULL - return a load of the original vector size that does not do any sign/zero ...
static SDValue AddCombineVUZPToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformADDCombineWithOperands(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombineWithOperands - Try DAG combinations for an ADD with operands N0 and N1.
static SDValue PromoteMVEPredVector(SDLoc dl, SDValue Pred, EVT VT, SelectionDAG &DAG)
static 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 SDValue ConvertCarryFlagToBooleanCarry(SDValue Flags, EVT VT, SelectionDAG &DAG)
static void checkVSELConstraints(ISD::CondCode CC, ARMCC::CondCodes &CondCode, bool &swpCmpOps, bool &swpVselOps)
static void ReplaceLongIntrinsic(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isS16(const SDValue &Op, SelectionDAG &DAG)
static bool isSRA16(const SDValue &Op)
static SDValue AddCombineBUILD_VECTORToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerVECTOR_SHUFFLEUsingMovs(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue LowerInterruptReturn(SmallVectorImpl< SDValue > &RetOps, const SDLoc &DL, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue 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 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...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
bool isZEXTLoad(const SDNode *N)
Returns true if the specified node is a ZEXTLOAD.
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, EVT Type)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
bool isEXTLoad(const SDNode *N)
Returns true if the specified node is a EXTLOAD.
LLVM_ABI CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
bool isSignedIntSetCC(CondCode Code)
Return true if this is a setcc instruction that performs a signed comparison when used with integer o...
LLVM_ABI bool isConstantSplatVector(const SDNode *N, APInt &SplatValue)
Node predicates.
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
bool isSEXTLoad(const SDNode *N)
Returns true if the specified node is a SEXTLOAD.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
static const int LAST_INDEXED_MODE
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
LLVM_ABI Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPEXT(EVT OpVT, EVT RetVT)
getFPEXT - Return the FPEXT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
LLVM_ABI Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
bool RetFastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
FunctionAddr VTableAddr Value
void stable_sort(R &&Range)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool HasLowerConstantMaterializationCost(unsigned Val1, unsigned Val2, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns true if Val1 has a lower Constant Materialization Cost than Val2.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Define
Register definition.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
bool CC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
constexpr bool isMask_32(uint32_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
@ SjLj
setjmp/longjmp based exceptions
bool RetCC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
bool RetCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
int bit_width(T Value)
Returns the number of bits needed to represent Value if Value is nonzero.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
bool RetCC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI Value * concatenateVectors(IRBuilderBase &Builder, ArrayRef< Value * > Vecs)
Concatenate a list of vectors.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
void shuffle(Iterator first, Iterator last, RNG &&g)
bool CC_ARM_APCS_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
constexpr bool isShiftedMask_32(uint32_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (32 bit ver...
LLVM_ABI ConstantFPSDNode * isConstOrConstSplatFP(SDValue N, bool AllowUndefs=false)
Returns the SDNode if it is a constant splat BuildVector or constant float.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
bool isReleaseOrStronger(AtomicOrdering AO)
auto dyn_cast_or_null(const Y &Val)
constexpr bool has_single_bit(T Value) noexcept
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
LLVM_ABI bool isBitwiseNot(SDValue V, bool AllowUndefs=false)
Returns true if V is a bitwise not operation.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
bool FastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
ComplexDeinterleavingOperation
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool CC_ARM_Win32_CFGuard_Check(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
FunctionAddr VTableAddr Count
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
ComplexDeinterleavingRotation
FunctionAddr VTableAddr uintptr_t uintptr_t Data
unsigned ConstantMaterializationCost(unsigned Val, const ARMSubtarget *Subtarget, bool ForCodesize=false)
Returns the number of instructions required to materialize the given constant in a register,...
@ Mul
Product of integers.
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
constexpr U AbsoluteValue(T X)
Return the absolute value of a signed integer, converted to the corresponding unsigned integer type.
bool isAcquireOrStronger(AtomicOrdering AO)
constexpr unsigned BitWidth
static MachineOperand t1CondCodeOp(bool isDead=false)
Get the operand corresponding to the conditional code result for Thumb1.
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
bool isVREVMask(ArrayRef< int > M, EVT VT, unsigned BlockSize)
isVREVMask - Check if a vector shuffle corresponds to a VREV instruction with the specified blocksize...
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
unsigned gettBLXrOpcode(const MachineFunction &MF)
bool CC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
@ Increment
Incrementally increasing token ID.
bool CC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
LLVM_ABI llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
constexpr bool isShiftedUInt(uint64_t x)
Checks if a unsigned integer is an N bit number shifted left by S.
unsigned convertAddSubFlagsOpcode(unsigned OldOpc)
Map pseudo instructions that imply an 'S' bit onto real opcodes.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
static const unsigned PerfectShuffleTable[6561+1]
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Load/store instruction that can be merged with a base address update.
SDNode * N
Instruction that updates a pointer.
unsigned ConstInc
Pointer increment value if it is a constant, or 0 otherwise.
SDValue Inc
Pointer increment operand.
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
static constexpr DenormalMode getIEEE()
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
EVT changeVectorElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
uint64_t getFixedSizeInBits() const
Return the size of the specified fixed width value type in bits.
bool isFixedLengthVector() const
static EVT getFloatingPointVT(unsigned BitWidth)
Returns the EVT that represents a floating-point type with the given number of bits.
bool isVector() const
Return true if this is a vector value type.
EVT getScalarType() const
If this is a vector type, return the element type, otherwise return this.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isScalarInteger() const
Return true if this is an integer, but not a vector.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
EVT getHalfNumVectorElementsVT(LLVMContext &Context) const
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool is64BitVector() const
Return true if this is a 64-bit vector type.
static KnownBits makeConstant(const APInt &C)
Create known bits from a known constant.
bool isUnknown() const
Returns true if we don't know any bits.
unsigned getBitWidth() const
Get the bit width of this value.
KnownBits zext(unsigned BitWidth) const
Return known bits for a zero extension of the value we're tracking.
void resetAll()
Resets the known state of all bits.
KnownBits intersectWith(const KnownBits &RHS) const
Returns KnownBits information that is known to be true for both this and RHS.
KnownBits sext(unsigned BitWidth) const
Return known bits for a sign extension of the value we're tracking.
static KnownBits add(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false)
Compute knownbits resulting from addition of LHS and RHS.
static LLVM_ABI KnownBits mul(const KnownBits &LHS, const KnownBits &RHS, bool NoUndefSelfMultiply=false)
Compute known bits resulting from multiplying LHS and RHS.
APInt getSignedMinValue() const
Return the minimal signed value possible given these KnownBits.
SmallVector< ArgRegPair, 1 > ArgRegPairs
Vector of call argument and its forwarding register.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getJumpTable(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a jump table entry.
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
These are IR-level optimization flags that may be propagated to SDNodes.
bool hasNoSignedZeros() const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This contains information for each constraint that we are lowering.
This structure contains all information that is necessary for lowering calls.
CallLoweringInfo & setInRegister(bool Value=true)
CallLoweringInfo & setLibCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList)
SmallVector< ISD::InputArg, 32 > Ins
const ConstantInt * CFIType
CallLoweringInfo & setZExtResult(bool Value=true)
CallLoweringInfo & setDebugLoc(const SDLoc &dl)
CallLoweringInfo & setSExtResult(bool Value=true)
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
CallLoweringInfo & setChain(SDValue InChain)
CallLoweringInfo & setCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList, AttributeSet ResultAttrs={})
bool isAfterLegalizeDAG() const
LLVM_ABI void AddToWorklist(SDNode *N)
bool isCalledByLegalizer() const
bool isBeforeLegalize() const
LLVM_ABI SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
This structure is used to pass arguments to makeLibCall function.
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)