84#include "llvm/IR/IntrinsicsARM.h"
120#define DEBUG_TYPE "arm-isel"
123STATISTIC(NumMovwMovt,
"Number of GAs materialized with movw + movt");
124STATISTIC(NumLoopByVals,
"Number of loops generated for byval arguments");
126 "Number of constants with their storage promoted into constant pools");
130 cl::desc(
"Enable / disable ARM interworking (for debugging only)"),
135 cl::desc(
"Enable / disable promotion of unnamed_addr constants into "
140 cl::desc(
"Maximum size of constant to promote into a constant pool"),
144 cl::desc(
"Maximum size of ALL constants to promote into a constant pool"),
149 cl::desc(
"Maximum interleave factor for MVE VLDn to generate."),
157 ARM::R0, ARM::R1, ARM::R2, ARM::R3
171void ARMTargetLowering::addTypeForNEON(
MVT VT,
MVT PromotedLdStVT) {
172 if (VT != PromotedLdStVT) {
181 if (ElemTy != MVT::f64)
185 if (ElemTy == MVT::i32) {
229void ARMTargetLowering::addDRTypeForNEON(
MVT VT) {
231 addTypeForNEON(VT, MVT::f64);
234void ARMTargetLowering::addQRTypeForNEON(
MVT VT) {
236 addTypeForNEON(VT, MVT::v2f64);
239void ARMTargetLowering::setAllExpand(
MVT VT) {
252void ARMTargetLowering::addAllExtLoads(
const MVT From,
const MVT To,
253 LegalizeAction Action) {
259void ARMTargetLowering::addMVEVectorTypes(
bool HasMVEFP) {
260 const MVT IntTypes[] = { MVT::v16i8, MVT::v8i16, MVT::v4i32 };
262 for (
auto VT : IntTypes) {
336 const MVT FloatTypes[] = { MVT::v8f16, MVT::v4f32 };
337 for (
auto VT : FloatTypes) {
406 const MVT LongTypes[] = { MVT::v2i64, MVT::v2f64 };
407 for (
auto VT : LongTypes) {
424 addAllExtLoads(MVT::v8i16, MVT::v8i8,
Legal);
425 addAllExtLoads(MVT::v4i32, MVT::v4i16,
Legal);
426 addAllExtLoads(MVT::v4i32, MVT::v4i8,
Legal);
443 for (
auto VT : {MVT::v8i8, MVT::v4i8, MVT::v4i16}) {
452 const MVT pTypes[] = {MVT::v16i1, MVT::v8i1, MVT::v4i1, MVT::v2i1};
453 for (
auto VT : pTypes) {
509 for (
int LCID = 0; LCID < RTLIB::UNKNOWN_LIBCALL; ++LCID)
517 if (Subtarget->isThumb() && Subtarget->
hasVFP2Base() &&
518 Subtarget->
hasARMOps() && !Subtarget->useSoftFloat()) {
519 static const struct {
521 const char *
const Name;
543 { RTLIB::UO_F32,
"__unordsf2vfp",
ISD::SETNE },
552 { RTLIB::UO_F64,
"__unorddf2vfp",
ISD::SETNE },
577 for (
const auto &LC : LibraryCalls) {
589 static const struct {
591 const char *
const Name;
676 for (
const auto &LC : LibraryCalls) {
686 static const struct {
688 const char *
const Name;
691 } MemOpsLibraryCalls[] = {
699 for (
const auto &LC : MemOpsLibraryCalls) {
709 static const struct {
711 const char *
const Name;
724 for (
const auto &LC : LibraryCalls) {
756 static const struct {
758 const char *
const Name;
766 for (
const auto &LC : LibraryCalls) {
777 if (!Subtarget->useSoftFloat() && !Subtarget->
isThumb1Only() &&
778 Subtarget->hasFPRegs()) {
788 setAllExpand(MVT::f32);
789 if (!Subtarget->hasFP64())
790 setAllExpand(MVT::f64);
793 if (Subtarget->hasFullFP16()) {
802 if (Subtarget->hasBF16()) {
804 setAllExpand(MVT::bf16);
805 if (!Subtarget->hasFullFP16())
815 addAllExtLoads(VT, InnerVT,
Expand);
830 if (Subtarget->hasMVEIntegerOps())
831 addMVEVectorTypes(Subtarget->hasMVEFloatOps());
834 if (Subtarget->hasLOB()) {
838 if (Subtarget->hasNEON()) {
839 addDRTypeForNEON(MVT::v2f32);
840 addDRTypeForNEON(MVT::v8i8);
841 addDRTypeForNEON(MVT::v4i16);
842 addDRTypeForNEON(MVT::v2i32);
843 addDRTypeForNEON(MVT::v1i64);
845 addQRTypeForNEON(MVT::v4f32);
846 addQRTypeForNEON(MVT::v2f64);
847 addQRTypeForNEON(MVT::v16i8);
848 addQRTypeForNEON(MVT::v8i16);
849 addQRTypeForNEON(MVT::v4i32);
850 addQRTypeForNEON(MVT::v2i64);
852 if (Subtarget->hasFullFP16()) {
853 addQRTypeForNEON(MVT::v8f16);
854 addDRTypeForNEON(MVT::v4f16);
857 if (Subtarget->hasBF16()) {
858 addQRTypeForNEON(MVT::v8bf16);
859 addDRTypeForNEON(MVT::v4bf16);
863 if (Subtarget->hasMVEIntegerOps() || Subtarget->hasNEON()) {
903 if (Subtarget->hasNEON()) {
1017 for (
MVT Ty : {MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v4i16, MVT::v2i16,
1026 for (
auto VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v16i8, MVT::v8i16,
1035 if (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) {
1043 if (Subtarget->hasMVEIntegerOps()) {
1048 if (Subtarget->hasMVEFloatOps()) {
1052 if (!Subtarget->hasFP64()) {
1099 if (Subtarget->hasFullFP16()) {
1105 if (!Subtarget->hasFP16()) {
1156 if (Subtarget->hasDSP()) {
1178 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6Ops()
1179 || (Subtarget->
isThumb2() && !Subtarget->hasDSP()))
1194 if (Subtarget->hasMVEIntegerOps())
1204 if (!Subtarget->
isThumb1Only() && Subtarget->hasV6T2Ops())
1215 if (!Subtarget->hasV5TOps() || Subtarget->
isThumb1Only()) {
1224 if (Subtarget->hasPerfMon())
1228 if (!Subtarget->hasV6Ops())
1231 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
1232 : Subtarget->hasDivideInARMMode();
1239 if (Subtarget->
isTargetWindows() && !Subtarget->hasDivideInThumbMode()) {
1256 HasStandaloneRem =
false;
1261 const char *
const Name;
1263 } LibraryCalls[] = {
1275 for (
const auto &LC : LibraryCalls) {
1282 const char *
const Name;
1284 } LibraryCalls[] = {
1296 for (
const auto &LC : LibraryCalls) {
1334 InsertFencesForAtomic =
false;
1336 (!Subtarget->isThumb() || Subtarget->hasV8MBaselineOps())) {
1340 if (!Subtarget->isThumb() || !Subtarget->
isMClass())
1345 if (!Subtarget->hasAcquireRelease() ||
1348 InsertFencesForAtomic =
true;
1354 if (Subtarget->hasDataBarrier())
1355 InsertFencesForAtomic =
true;
1375 if (!InsertFencesForAtomic) {
1383 (!Subtarget->
isMClass() && Subtarget->hasV6Ops())) {
1395 }
else if ((Subtarget->
isMClass() && Subtarget->hasV8MBaselineOps()) ||
1396 Subtarget->hasForced32BitAtomics()) {
1410 if (!Subtarget->hasV6Ops()) {
1416 if (!Subtarget->useSoftFloat() && Subtarget->hasFPRegs() &&
1448 if (Subtarget->hasFullFP16()) {
1458 if (Subtarget->hasFullFP16())
1473 if (!Subtarget->useSoftFloat() && Subtarget->
hasVFP2Base() &&
1487 if (!Subtarget->useSoftFloat() && !Subtarget->
isThumb1Only()) {
1495 if (!Subtarget->hasFP16()) {
1526 if (Subtarget->hasNEON()) {
1533 if (Subtarget->hasFP64()) {
1546 if (Subtarget->hasFullFP16()) {
1565 if (Subtarget->hasNEON()) {
1577 if (Subtarget->hasFullFP16()) {
1609 if (Subtarget->hasMVEIntegerOps())
1612 if (Subtarget->hasV6Ops())
1617 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) ||
1624 if (Subtarget->useSoftFloat() || Subtarget->
isThumb1Only() ||
1653 return Subtarget->useSoftFloat();
1666std::pair<const TargetRegisterClass *, uint8_t>
1677 case MVT::f32:
case MVT::f64:
case MVT::v8i8:
case MVT::v4i16:
1678 case MVT::v2i32:
case MVT::v1i64:
case MVT::v2f32:
1679 RRC = &ARM::DPRRegClass;
1687 case MVT::v16i8:
case MVT::v8i16:
case MVT::v4i32:
case MVT::v2i64:
1688 case MVT::v4f32:
case MVT::v2f64:
1689 RRC = &ARM::DPRRegClass;
1693 RRC = &ARM::DPRRegClass;
1697 RRC = &ARM::DPRRegClass;
1701 return std::make_pair(RRC,
Cost);
1705#define MAKE_CASE(V) \
1924 if ((Subtarget->hasMVEIntegerOps() &&
1925 (VT == MVT::v2i64 || VT == MVT::v4i32 || VT == MVT::v8i16 ||
1926 VT == MVT::v16i8)) ||
1927 (Subtarget->hasMVEFloatOps() &&
1928 (VT == MVT::v2f64 || VT == MVT::v4f32 || VT == MVT::v8f16)))
1942 if (Subtarget->hasNEON()) {
1943 if (VT == MVT::v4i64)
1944 return &ARM::QQPRRegClass;
1945 if (VT == MVT::v8i64)
1946 return &ARM::QQQQPRRegClass;
1948 if (Subtarget->hasMVEIntegerOps()) {
1949 if (VT == MVT::v4i64)
1950 return &ARM::MQQPRRegClass;
1951 if (VT == MVT::v8i64)
1952 return &ARM::MQQQQPRRegClass;
1961 Align &PrefAlign)
const {
1962 if (!isa<MemIntrinsic>(CI))
1980 unsigned NumVals =
N->getNumValues();
1984 for (
unsigned i = 0; i != NumVals; ++i) {
1985 EVT VT =
N->getValueType(i);
1986 if (VT == MVT::Glue || VT == MVT::Other)
1992 if (!
N->isMachineOpcode())
2016 if (
auto Const = dyn_cast<ConstantSDNode>(
Op.getOperand(1)))
2017 return Const->getZExtValue() == 16;
2024 if (
auto Const = dyn_cast<ConstantSDNode>(
Op.getOperand(1)))
2025 return Const->getZExtValue() == 16;
2032 if (
auto Const = dyn_cast<ConstantSDNode>(
Op.getOperand(1)))
2033 return Const->getZExtValue() == 16;
2102 bool isVarArg)
const {
2123 else if (Subtarget->hasFPRegs() && !Subtarget->
isThumb1Only() &&
2144 bool isVarArg)
const {
2145 return CCAssignFnForNode(
CC,
false, isVarArg);
2149 bool isVarArg)
const {
2150 return CCAssignFnForNode(
CC,
true, isVarArg);
2157 bool isVarArg)
const {
2158 switch (getEffectiveCallingConv(
CC, isVarArg)) {
2184 if (Subtarget->hasFullFP16()) {
2197 if (Subtarget->hasFullFP16()) {
2211SDValue ARMTargetLowering::LowerCallResult(
2215 SDValue ThisVal,
bool isCmseNSCall)
const {
2223 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
2228 if (i == 0 && isThisReturn) {
2230 "unexpected return calling convention register assignment");
2241 Chain =
Lo.getValue(1);
2242 InGlue =
Lo.getValue(2);
2246 Chain =
Hi.getValue(1);
2247 InGlue =
Hi.getValue(2);
2259 Chain =
Lo.getValue(1);
2260 InGlue =
Lo.getValue(2);
2263 Chain =
Hi.getValue(1);
2264 InGlue =
Hi.getValue(2);
2308std::pair<SDValue, MachinePointerInfo> ARMTargetLowering::computeAddrForCallArg(
2310 bool IsTailCall,
int SPDiff)
const {
2332 return std::make_pair(DstAddr, DstInfo);
2341ARMTargetLowering::ByValCopyKind ARMTargetLowering::ByValNeedsCopyForTailCall(
2347 if (isa<GlobalAddressSDNode>(Src) || isa<ExternalSymbolSDNode>(Src))
2352 auto *SrcFrameIdxNode = dyn_cast<FrameIndexSDNode>(Src);
2353 auto *DstFrameIdxNode = dyn_cast<FrameIndexSDNode>(Dst);
2354 if (!SrcFrameIdxNode || !DstFrameIdxNode)
2357 int SrcFI = SrcFrameIdxNode->getIndex();
2358 int DstFI = DstFrameIdxNode->getIndex();
2360 "byval passed in non-fixed stack slot");
2382 if (SrcOffset == DstOffset)
2390 RegsToPassVector &RegsToPass,
2397 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
2398 unsigned id = Subtarget->
isLittle() ? 0 : 1;
2411 std::tie(DstAddr, DstInfo) =
2412 computeAddrForCallArg(dl, DAG, NextVA, StackPtr, IsTailCall, SPDiff);
2445 bool isStructRet = (Outs.
empty()) ?
false : Outs[0].
Flags.isSRet();
2446 bool isThisReturn =
false;
2447 bool isCmseNSCall =
false;
2448 bool isSibCall =
false;
2449 bool PreferIndirect =
false;
2450 bool GuardWithBTI =
false;
2460 !Subtarget->noBTIAtReturnTwice())
2465 isCmseNSCall =
true;
2477 if (isa<GlobalAddressSDNode>(Callee)) {
2481 auto *GV = cast<GlobalAddressSDNode>(Callee)->getGlobal();
2484 PreferIndirect = Subtarget->isThumb() && Subtarget->
hasMinSize() &&
2486 return isa<Instruction>(U) &&
2487 cast<Instruction>(U)->getParent() == BB;
2494 IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
2508 "site marked musttail");
2511 unsigned NumBytes = CCInfo.getStackSize();
2520 if (isTailCall && !isSibCall) {
2527 assert(StackAlign &&
"data layout string is missing stack alignment");
2528 NumBytes =
alignTo(NumBytes, *StackAlign);
2533 SPDiff = NumReusableBytes - NumBytes;
2537 if (SPDiff < 0 && AFI->getArgRegsSaveSize() < (
unsigned)-SPDiff)
2553 RegsToPassVector RegsToPass;
2568 SDValue Src = OutVals[ArgIdx];
2571 if (!
Flags.isByVal())
2576 std::tie(Dst, DstInfo) =
2577 computeAddrForCallArg(dl, DAG, VA,
SDValue(),
true, SPDiff);
2578 ByValCopyKind
Copy = ByValNeedsCopyForTailCall(DAG, Src, Dst, Flags);
2580 if (Copy == NoCopy) {
2585 }
else if (Copy == CopyOnce) {
2589 ByValTemporaries[ArgIdx] = Src;
2591 assert(Copy == CopyViaTemp &&
"unexpected enum value");
2595 int TempFrameIdx = MFI.CreateStackObject(
2596 Flags.getByValSize(),
Flags.getNonZeroByValAlign(),
false);
2605 SDValue Ops[] = {Chain, Temp, Src, SizeNode, AlignNode};
2608 ByValTemporaries[ArgIdx] = Temp;
2611 if (!ByValCopyChains.
empty())
2621 bool AfterFormalArgLoads =
false;
2625 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
2627 ++i, ++realArgIdx) {
2629 SDValue Arg = OutVals[realArgIdx];
2631 bool isByVal =
Flags.isByVal();
2651 if (isTailCall && VA.
isMemLoc() && !AfterFormalArgLoads) {
2656 AfterFormalArgLoads =
true;
2668 auto ArgVT = Outs[realArgIdx].ArgVT;
2669 if (isCmseNSCall && (ArgVT == MVT::f16)) {
2687 PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
2688 StackPtr, MemOpChains, isTailCall, SPDiff);
2692 PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
2693 StackPtr, MemOpChains, isTailCall, SPDiff);
2698 std::tie(DstAddr, DstInfo) =
2699 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2703 PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
2704 StackPtr, MemOpChains, isTailCall, SPDiff);
2706 if (realArgIdx == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
2707 Outs[0].VT == MVT::i32) {
2709 "unexpected calling convention register assignment");
2710 assert(!
Ins.empty() && Ins[0].VT == MVT::i32 &&
2711 "unexpected use of 'returned'");
2712 isThisReturn =
true;
2717 RegsToPass.push_back(std::make_pair(VA.
getLocReg(), Arg));
2718 }
else if (isByVal) {
2720 unsigned offset = 0;
2724 unsigned ByValArgsCount = CCInfo.getInRegsParamsCount();
2725 unsigned CurByValIdx = CCInfo.getInRegsParamsProcessed();
2728 bool NeedsStackCopy;
2729 if (ByValTemporaries.
contains(realArgIdx)) {
2730 ByValSrc = ByValTemporaries[realArgIdx];
2731 NeedsStackCopy =
true;
2734 NeedsStackCopy = !isTailCall;
2738 if (CurByValIdx < ByValArgsCount) {
2739 unsigned RegBegin, RegEnd;
2740 CCInfo.getInRegsParamInfo(CurByValIdx, RegBegin, RegEnd);
2745 for (i = 0, j = RegBegin;
j < RegEnd; i++,
j++) {
2752 RegsToPass.push_back(std::make_pair(j, Load));
2757 offset = RegEnd - RegBegin;
2759 CCInfo.nextInRegsParam();
2764 if (NeedsStackCopy &&
Flags.getByValSize() > 4 * offset) {
2768 std::tie(Dst, DstInfo) =
2769 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2778 SDValue Ops[] = { Chain, Dst, Src, SizeNode, AlignNode};
2786 std::tie(DstAddr, DstInfo) =
2787 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2794 if (!MemOpChains.
empty())
2800 for (
unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
2801 Chain = DAG.
getCopyToReg(Chain, dl, RegsToPass[i].first,
2802 RegsToPass[i].second, InGlue);
2809 bool isDirect =
false;
2814 GVal =
G->getGlobal();
2815 bool isStub = !
TM.shouldAssumeDSOLocal(GVal) && Subtarget->
isTargetMachO();
2817 bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->
isMClass());
2818 bool isLocalARMFunc =
false;
2821 if (Subtarget->genLongCalls()) {
2823 "long-calls codegen is not position independent!");
2827 if (isa<GlobalAddressSDNode>(Callee)) {
2828 if (Subtarget->genExecuteOnly()) {
2847 const char *
Sym = S->getSymbol();
2849 if (Subtarget->genExecuteOnly()) {
2868 }
else if (isa<GlobalAddressSDNode>(Callee)) {
2869 if (!PreferIndirect) {
2874 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !
ARMInterworking);
2876 if (isStub && Subtarget->
isThumb1Only() && !Subtarget->hasV5TOps()) {
2888 "Windows is the only supported COFF target");
2892 else if (!
TM.shouldAssumeDSOLocal(GVal))
2908 const char *
Sym = S->getSymbol();
2909 if (isARMFunc && Subtarget->
isThumb1Only() && !Subtarget->hasV5TOps()) {
2913 ARMPCLabelIndex, 4);
2927 assert(!isARMFunc && !isDirect &&
2928 "Cannot handle call to ARM function or direct call");
2931 "call to non-secure function would "
2932 "require passing arguments on stack",
2939 "call to non-secure function would return value through pointer",
2947 if (Subtarget->isThumb()) {
2950 else if (isCmseNSCall)
2952 else if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
2957 if (!isDirect && !Subtarget->hasV5TOps())
2959 else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() &&
2972 if (isTailCall && !isSibCall) {
2977 std::vector<SDValue> Ops;
2978 Ops.push_back(Chain);
2979 Ops.push_back(Callee);
2987 for (
unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
2988 Ops.push_back(DAG.
getRegister(RegsToPass[i].first,
2989 RegsToPass[i].second.getValueType()));
3001 isThisReturn =
false;
3007 assert(Mask &&
"Missing call preserved mask for calling convention");
3011 Ops.push_back(InGlue);
3022 Chain = DAG.
getNode(CallOpc, dl, {MVT::Other, MVT::Glue}, Ops);
3034 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, dl);
3040 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
3041 InVals, isThisReturn,
3042 isThisReturn ? OutVals[0] :
SDValue(), isCmseNSCall);
3049void ARMTargetLowering::HandleByVal(
CCState *State,
unsigned &
Size,
3050 Align Alignment)
const {
3052 Alignment = std::max(Alignment,
Align(4));
3058 unsigned AlignInRegs = Alignment.
value() / 4;
3059 unsigned Waste = (ARM::R4 -
Reg) % AlignInRegs;
3060 for (
unsigned i = 0; i < Waste; ++i)
3066 unsigned Excess = 4 * (ARM::R4 -
Reg);
3073 if (NSAAOffset != 0 &&
Size > Excess) {
3085 unsigned ByValRegBegin =
Reg;
3086 unsigned ByValRegEnd = std::min<unsigned>(Reg +
Size / 4, ARM::R4);
3090 for (
unsigned i = Reg + 1; i != ByValRegEnd; ++i)
3096 Size = std::max<int>(
Size - Excess, 0);
3104bool ARMTargetLowering::IsEligibleForTailCallOptimization(
3130 if (!isa<GlobalAddressSDNode>(
Callee.getNode()) || isIndirect) {
3132 for (
Register R : {ARM::R0, ARM::R1, ARM::R2, ARM::R3})
3133 AddressRegisters.
insert(R);
3136 AddressRegisters.
insert(ARM::R12);
3139 AddressRegisters.
erase(
AL.getLocReg());
3140 if (AddressRegisters.
empty()) {
3141 LLVM_DEBUG(
dbgs() <<
"false (no reg to hold function pointer)\n");
3160 <<
" (guaranteed tail-call CC)\n");
3161 return CalleeCC == CallerCC;
3166 bool isCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
3168 if (isCalleeStructRet != isCallerStructRet) {
3184 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
3185 TT.isOSBinFormatMachO())) {
3194 getEffectiveCallingConv(CalleeCC, isVarArg),
3195 getEffectiveCallingConv(CallerCC, CallerF.
isVarArg()), MF,
C, Ins,
3203 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
3204 if (CalleeCC != CallerCC) {
3205 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
3206 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) {
3225 LLVM_DEBUG(
dbgs() <<
"false (parameters in CSRs do not match)\n");
3244 CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
3253 StringRef IntKind =
F.getFnAttribute(
"interrupt").getValueAsString();
3266 if (IntKind ==
"" || IntKind ==
"IRQ" || IntKind ==
"FIQ" ||
3269 else if (IntKind ==
"SWI" || IntKind ==
"UNDEF")
3273 "must be one of: IRQ, FIQ, SWI, ABORT or UNDEF");
3300 bool isLittleEndian = Subtarget->
isLittle();
3312 "secure entry function would return value through pointer",
3318 for (
unsigned i = 0, realRVLocIdx = 0;
3320 ++i, ++realRVLocIdx) {
3324 SDValue Arg = OutVals[realRVLocIdx];
3325 bool ReturnF16 =
false;
3360 auto RetVT = Outs[realRVLocIdx].ArgVT;
3382 DAG.
getVTList(MVT::i32, MVT::i32), Half);
3386 HalfGPRs.
getValue(isLittleEndian ? 0 : 1), Glue);
3392 HalfGPRs.
getValue(isLittleEndian ? 1 : 0), Glue);
3404 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
3406 fmrrd.
getValue(isLittleEndian ? 0 : 1), Glue);
3411 fmrrd.
getValue(isLittleEndian ? 1 : 0), Glue);
3455 return DAG.
getNode(RetNode, dl, MVT::Other, RetOps);
3458bool ARMTargetLowering::isUsedByReturnOnly(
SDNode *
N,
SDValue &Chain)
const {
3459 if (
N->getNumValues() != 1)
3461 if (!
N->hasNUsesOfValue(1, 0))
3469 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3471 TCChain =
Copy->getOperand(0);
3485 SDValue UseChain =
U->getOperand(0);
3493 if (
U->getOperand(
U->getNumOperands() - 1).getValueType() == MVT::Glue)
3501 if (!
Copy->hasOneUse())
3508 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3510 TCChain =
Copy->getOperand(0);
3515 bool HasRet =
false;
3530bool ARMTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
3548 &&
"LowerWRITE_REGISTER called for non-i64 type argument.");
3564 EVT PtrVT =
Op.getValueType();
3574 if (Subtarget->genExecuteOnly()) {
3576 auto T =
const_cast<Type*
>(
CP->getType());
3577 auto C =
const_cast<Constant*
>(
CP->getConstVal());
3588 return LowerGlobalAddress(GA, DAG);
3593 Align CPAlign =
CP->getAlign();
3595 CPAlign = std::max(CPAlign,
Align(4));
3596 if (
CP->isMachineConstantPoolEntry())
3608 if (Subtarget->genExecuteOnly() && !Subtarget->hasV8MBaselineOps())
3617 unsigned ARMPCLabelIndex = 0;
3620 const BlockAddress *BA = cast<BlockAddressSDNode>(
Op)->getBlockAddress();
3623 if (!IsPositionIndependent) {
3626 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
3637 if (!IsPositionIndependent)
3668ARMTargetLowering::LowerGlobalTLSAddressDarwin(
SDValue Op,
3671 "This function expects a Darwin target");
3676 SDValue DescAddr = LowerGlobalAddressDarwin(
Op, DAG);
3682 MVT::i32,
DL, Chain, DescAddr,
3706 Chain, FuncTLVGet, DAG.
getRegister(ARM::R0, MVT::i32),
3712ARMTargetLowering::LowerGlobalTLSAddressWindows(
SDValue Op,
3729 DAG.
getVTList(MVT::i32, MVT::Other), Ops);
3756 const auto *GA = cast<GlobalAddressSDNode>(
Op);
3773 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3795 Args.push_back(Entry);
3803 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3804 return CallResult.first;
3826 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3834 PtrVT, dl, Chain,
Offset,
3836 Chain =
Offset.getValue(1);
3842 PtrVT, dl, Chain,
Offset,
3852 PtrVT, dl, Chain,
Offset,
3868 return LowerGlobalTLSAddressDarwin(
Op, DAG);
3871 return LowerGlobalTLSAddressWindows(
Op, DAG);
3880 return LowerToTLSGeneralDynamicModel(GA, DAG);
3883 return LowerToTLSExecModels(GA, DAG, model);
3892 while (!Worklist.
empty()) {
3894 if (isa<ConstantExpr>(U)) {
3899 auto *
I = dyn_cast<Instruction>(U);
3900 if (!
I ||
I->getParent()->getParent() !=
F)
3928 auto *GVar = dyn_cast<GlobalVariable>(GV);
3929 if (!GVar || !GVar->hasInitializer() ||
3930 !GVar->isConstant() || !GVar->hasGlobalUnnamedAddr() ||
3931 !GVar->hasLocalLinkage())
3936 auto *
Init = GVar->getInitializer();
3938 Init->needsDynamicRelocation())
3947 auto *CDAInit = dyn_cast<ConstantDataArray>(
Init);
3950 unsigned RequiredPadding = 4 - (
Size % 4);
3951 bool PaddingPossible =
3952 RequiredPadding == 4 || (CDAInit && CDAInit->isString());
3957 unsigned PaddedSize =
Size + ((RequiredPadding == 4) ? 0 : RequiredPadding);
3981 if (RequiredPadding != 4) {
3986 while (RequiredPadding--)
3998 ++NumConstpoolPromoted;
4003 if (
const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
4004 if (!(GV = GA->getAliaseeObject()))
4006 if (
const auto *V = dyn_cast<GlobalVariable>(GV))
4007 return V->isConstant();
4008 return isa<Function>(GV);
4016 return LowerGlobalAddressWindows(
Op, DAG);
4018 return LowerGlobalAddressELF(
Op, DAG);
4020 return LowerGlobalAddressDarwin(
Op, DAG);
4028 const GlobalValue *GV = cast<GlobalAddressSDNode>(
Op)->getGlobal();
4032 if (GV->
isDSOLocal() && !Subtarget->genExecuteOnly())
4045 }
else if (Subtarget->
isROPI() && IsRO) {
4050 }
else if (Subtarget->
isRWPI() && !IsRO) {
4075 if (Subtarget->
useMovt() || Subtarget->genExecuteOnly()) {
4094 "ROPI/RWPI not currently supported for Darwin");
4097 const GlobalValue *GV = cast<GlobalAddressSDNode>(
Op)->getGlobal();
4120 "Windows on ARM expects to use movw/movt");
4122 "ROPI/RWPI not currently supported for Windows");
4125 const GlobalValue *GV = cast<GlobalAddressSDNode>(
Op)->getGlobal();
4129 else if (!
TM.shouldAssumeDSOLocal(GV))
4153 DAG.
getVTList(MVT::i32, MVT::Other),
Op.getOperand(0),
4154 Op.getOperand(1), Val);
4171SDValue ARMTargetLowering::LowerINTRINSIC_VOID(
4174 Op.getConstantOperandVal(
Op.getOperand(0).getValueType() == MVT::Other);
4178 case Intrinsic::arm_gnu_eabi_mcount: {
4187 assert(Mask &&
"Missing call preserved mask for calling convention");
4192 constexpr EVT ResultTys[] = {MVT::Other, MVT::Glue};
4196 if (Subtarget->isThumb())
4199 ARM::tBL_PUSHLR, dl, ResultTys,
4200 {ReturnAddress, DAG.getTargetConstant(ARMCC::AL, dl, PtrVT),
4201 DAG.getRegister(0, PtrVT), Callee, RegisterMask, Chain}),
4205 {ReturnAddress, Callee, RegisterMask, Chain}),
4214 unsigned IntNo =
Op.getConstantOperandVal(0);
4218 case Intrinsic::thread_pointer: {
4222 case Intrinsic::arm_cls: {
4223 const SDValue &Operand =
Op.getOperand(1);
4224 const EVT VTy =
Op.getValueType();
4235 case Intrinsic::arm_cls64: {
4238 const SDValue &Operand =
Op.getOperand(1);
4239 const EVT VTy =
Op.getValueType();
4262 case Intrinsic::eh_sjlj_lsda: {
4269 unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
4279 if (IsPositionIndependent) {
4285 case Intrinsic::arm_neon_vabs:
4288 case Intrinsic::arm_neon_vabds:
4289 if (
Op.getValueType().isInteger())
4291 Op.getOperand(1),
Op.getOperand(2));
4293 case Intrinsic::arm_neon_vabdu:
4295 Op.getOperand(1),
Op.getOperand(2));
4296 case Intrinsic::arm_neon_vmulls:
4297 case Intrinsic::arm_neon_vmullu: {
4298 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmulls)
4301 Op.getOperand(1),
Op.getOperand(2));
4303 case Intrinsic::arm_neon_vminnm:
4304 case Intrinsic::arm_neon_vmaxnm: {
4305 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminnm)
4308 Op.getOperand(1),
Op.getOperand(2));
4310 case Intrinsic::arm_neon_vminu:
4311 case Intrinsic::arm_neon_vmaxu: {
4312 if (
Op.getValueType().isFloatingPoint())
4314 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminu)
4317 Op.getOperand(1),
Op.getOperand(2));
4319 case Intrinsic::arm_neon_vmins:
4320 case Intrinsic::arm_neon_vmaxs: {
4322 if (!
Op.getValueType().isFloatingPoint()) {
4323 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
4326 Op.getOperand(1),
Op.getOperand(2));
4328 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
4331 Op.getOperand(1),
Op.getOperand(2));
4333 case Intrinsic::arm_neon_vtbl1:
4335 Op.getOperand(1),
Op.getOperand(2));
4336 case Intrinsic::arm_neon_vtbl2:
4338 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4339 case Intrinsic::arm_mve_pred_i2v:
4340 case Intrinsic::arm_mve_pred_v2i:
4343 case Intrinsic::arm_mve_vreinterpretq:
4346 case Intrinsic::arm_mve_lsll:
4348 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4349 case Intrinsic::arm_mve_asrl:
4351 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4362 if (!Subtarget->hasDataBarrier()) {
4366 assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() &&
4367 "Unexpected ISD::ATOMIC_FENCE encountered. Should be libcall!");
4378 }
else if (Subtarget->preferISHSTBarriers() &&
4387 DAG.
getConstant(Intrinsic::arm_dmb, dl, MVT::i32),
4395 (!Subtarget->
isThumb1Only() && Subtarget->hasV5TEOps())))
4397 return Op.getOperand(0);
4400 unsigned isRead =
~Op.getConstantOperandVal(2) & 1;
4402 (!Subtarget->hasV7Ops() || !Subtarget->hasMPExtension()))
4404 return Op.getOperand(0);
4406 unsigned isData =
Op.getConstantOperandVal(4);
4407 if (Subtarget->isThumb()) {
4409 isRead = ~isRead & 1;
4410 isData = ~isData & 1;
4427 const Value *SV = cast<SrcValueSDNode>(
Op.getOperand(2))->getValue();
4428 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
4436 const SDLoc &dl)
const {
4442 RC = &ARM::tGPRRegClass;
4444 RC = &ARM::GPRRegClass;
4458 MVT::i32, dl, Root, FIN,
4479 const Value *OrigArg,
4480 unsigned InRegsParamRecordIdx,
4481 int ArgOffset,
unsigned ArgSize)
const {
4496 unsigned RBegin, REnd;
4506 ArgOffset = -4 * (ARM::R4 - RBegin);
4516 for (
unsigned Reg = RBegin, i = 0;
Reg < REnd; ++
Reg, ++i) {
4525 if (!MemOps.
empty())
4534 unsigned TotalArgRegsSaveSize,
4535 bool ForceMutable)
const {
4546 CCInfo.
getStackSize(), std::max(4U, TotalArgRegsSaveSize));
4550bool ARMTargetLowering::splitValueIntoRegisterParts(
4552 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID>
CC)
const {
4554 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4566SDValue ARMTargetLowering::joinRegisterPartsIntoValue(
4568 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID>
CC)
const {
4569 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4582SDValue ARMTargetLowering::LowerFormalArguments(
4598 unsigned CurArgIdx = 0;
4610 unsigned ArgRegBegin = ARM::R4;
4617 if (!
Flags.isByVal())
4621 unsigned RBegin, REnd;
4623 ArgRegBegin = std::min(ArgRegBegin, RBegin);
4629 int lastInsIndex = -1;
4633 ArgRegBegin = std::min(ArgRegBegin, (
unsigned)
GPRArgRegs[RegIdx]);
4636 unsigned TotalArgRegsSaveSize = 4 * (ARM::R4 - ArgRegBegin);
4640 for (
unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4642 if (Ins[VA.
getValNo()].isOrigArg()) {
4643 std::advance(CurOrigArg,
4644 Ins[VA.
getValNo()].getOrigArgIndex() - CurArgIdx);
4656 GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4663 MVT::f64, dl, Chain, FIN,
4666 ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4674 ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4678 if (RegVT == MVT::f16 || RegVT == MVT::bf16)
4679 RC = &ARM::HPRRegClass;
4680 else if (RegVT == MVT::f32)
4681 RC = &ARM::SPRRegClass;
4682 else if (RegVT == MVT::f64 || RegVT == MVT::v4f16 ||
4683 RegVT == MVT::v4bf16)
4684 RC = &ARM::DPRRegClass;
4685 else if (RegVT == MVT::v2f64 || RegVT == MVT::v8f16 ||
4686 RegVT == MVT::v8bf16)
4687 RC = &ARM::QPRRegClass;
4688 else if (RegVT == MVT::i32)
4690 : &ARM::GPRRegClass;
4736 assert(VA.
getValVT() != MVT::i64 &&
"i64 should already be lowered");
4742 if (index != lastInsIndex)
4750 if (
Flags.isByVal()) {
4751 assert(Ins[index].isOrigArg() &&
4752 "Byval arguments cannot be implicit");
4756 CCInfo, DAG, dl, Chain, &*CurOrigArg, CurByValIndex,
4771 lastInsIndex = index;
4778 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.
getStackSize(),
4779 TotalArgRegsSaveSize);
4783 "secure entry function must not be variadic", dl.
getDebugLoc());
4794 assert(StackAlign &&
"data layout string is missing stack alignment");
4795 StackArgSize =
alignTo(StackArgSize, *StackAlign);
4804 "secure entry function requires arguments on stack", dl.
getDebugLoc());
4814 return CFP->getValueAPF().isPosZero();
4818 SDValue WrapperOp =
Op.getOperand(1).getOperand(0);
4820 if (
const ConstantFP *CFP = dyn_cast<ConstantFP>(CP->getConstVal()))
4821 return CFP->getValueAPF().isPosZero();
4824 Op->getValueType(0) == MVT::f64) {
4839 const SDLoc &dl)
const {
4841 unsigned C = RHSC->getZExtValue();
4907 LHS.getValueType() == MVT::i32 && isa<ConstantSDNode>(RHS) &&
4909 unsigned Mask =
LHS.getConstantOperandVal(1);
4910 auto *RHSC = cast<ConstantSDNode>(
RHS.getNode());
4911 uint64_t RHSV = RHSC->getZExtValue();
4912 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4914 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4929 isa<ConstantSDNode>(RHS) &&
RHS->getAsZExtVal() == 0x80000000U &&
4931 LHS.getConstantOperandVal(1) < 31) {
4932 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4975 bool Signaling)
const {
4976 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4991std::pair<SDValue, SDValue>
4994 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
5006 switch (
Op.getOpcode()) {
5019 DAG.
getVTList(
Op.getValueType(), MVT::i32), LHS, RHS)
5058 return std::make_pair(
Value, OverflowCmp);
5069 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
5074 EVT VT =
Op.getValueType();
5117 EVT VT =
Op.getValueType();
5121 switch (
Op.getOpcode()) {
5146 EVT VT =
Op.getValueType();
5147 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
5157 switch (
Op->getOpcode()) {
5173 switch (
Op->getOpcode()) {
5192 DAG.
getNode(NewOpcode, dl, MVT::i32,
5203 unsigned Opc =
Cond.getOpcode();
5205 if (
Cond.getResNo() == 1 &&
5213 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5214 EVT VT =
Op.getValueType();
5216 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, OverflowCmp, DAG);
5226 dyn_cast<ConstantSDNode>(
Cond.getOperand(0));
5228 dyn_cast<ConstantSDNode>(
Cond.getOperand(1));
5230 if (CMOVTrue && CMOVFalse) {
5236 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
5238 False = SelectFalse;
5239 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
5245 return getCMOV(dl,
Op.getValueType(), True, False,
Cond.getOperand(2),
5246 Cond.getOperand(3), DAG);
5261 bool &swpCmpOps,
bool &swpVselOps) {
5289 swpCmpOps = !swpCmpOps;
5290 swpVselOps = !swpVselOps;
5313 if (!Subtarget->hasFP64() && VT == MVT::f64) {
5315 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
5317 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
5352 ((K ==
LHS && K == TrueVal) || (K ==
RHS && K == FalseVal))) ||
5354 ((K ==
RHS && K == TrueVal) || (K ==
LHS && K == FalseVal)));
5375 EVT VT =
Op.getValueType();
5382 const SDValue Op2 = isa<ConstantSDNode>(TrueVal1) ? FalseVal1 : TrueVal1;
5397 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5405 if (!isa<ConstantSDNode>(K1) || !isa<ConstantSDNode>(K2))
5408 int64_t Val1 = cast<ConstantSDNode>(K1)->getSExtValue();
5409 int64_t Val2 = cast<ConstantSDNode>(K2)->getSExtValue();
5410 int64_t PosVal = std::max(Val1, Val2);
5411 int64_t NegVal = std::min(Val1, Val2);
5457 SDValue KTmp = isa<ConstantSDNode>(TrueVal) ? TrueVal : FalseVal;
5458 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5463 if (*K != KTmp || V != VTmp)
5474bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5478 return !Subtarget->hasFP64();
5480 return !Subtarget->hasFullFP16();
5485 EVT VT =
Op.getValueType();
5489 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->
isThumb2())
5501 if (VT == MVT::i32 &&
5521 if (Subtarget->hasV8_1MMainlineOps() && CFVal && CTVal &&
5522 LHS.getValueType() == MVT::i32 &&
RHS.getValueType() == MVT::i32) {
5525 unsigned Opcode = 0;
5527 if (TVal == ~FVal) {
5529 }
else if (TVal == ~FVal + 1) {
5531 }
else if (TVal + 1 == FVal) {
5533 }
else if (TVal == FVal + 1) {
5565 return DAG.
getNode(Opcode, dl, VT, TrueVal, FalseVal, ARMcc, Cmp);
5569 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5571 DAG,
LHS.getValueType(), LHS, RHS,
CC, dl, LHS, RHS);
5575 if (!
RHS.getNode()) {
5581 if (
LHS.getValueType() == MVT::i32) {
5593 TrueVal.getValueType() == MVT::f32 ||
5594 TrueVal.getValueType() == MVT::f64)) {
5608 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5620 (
TrueVal.getValueType() == MVT::f16 ||
5621 TrueVal.getValueType() == MVT::f32 ||
5622 TrueVal.getValueType() == MVT::f64)) {
5623 bool swpCmpOps =
false;
5624 bool swpVselOps =
false;
5638 SDValue Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5641 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, Cmp, DAG);
5651 if (!
N->hasOneUse())
5654 if (!
N->getNumValues())
5656 EVT VT =
Op.getValueType();
5657 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5674 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5675 Ld->getPointerInfo(), Ld->getAlign(),
5676 Ld->getMemOperand()->getFlags());
5694 DAG.
getLoad(MVT::i32, dl, Ld->getChain(),
Ptr, Ld->getPointerInfo(),
5695 Ld->getAlign(), Ld->getMemOperand()->getFlags());
5697 EVT PtrType =
Ptr.getValueType();
5700 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5701 Ld->getPointerInfo().getWithOffset(4),
5703 Ld->getMemOperand()->getFlags());
5721 bool LHSSeenZero =
false;
5723 bool RHSSeenZero =
false;
5725 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5736 if (
LHS.getValueType() == MVT::f32) {
5754 SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5769 unsigned Opc =
Cond.getOpcode();
5772 if (
Cond.getResNo() == 1 &&
5782 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5805 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5807 DAG,
LHS.getValueType(), LHS, RHS,
CC, dl, LHS, RHS);
5811 if (!
RHS.getNode()) {
5819 unsigned Opc =
LHS.getOpcode();
5833 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5847 if (
LHS.getValueType() == MVT::i32) {
5856 if (
SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5887 if (Subtarget->
isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5893 Addr,
Op.getOperand(2), JTI);
5899 Chain =
Addr.getValue(1);
5906 Chain =
Addr.getValue(1);
5912 EVT VT =
Op.getValueType();
5915 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5916 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5924 const EVT OpTy =
Op.getOperand(0).getValueType();
5925 if (OpTy == MVT::v4f32)
5927 else if (OpTy == MVT::v4f16 && HasFullFP16)
5929 else if (OpTy == MVT::v8f16 && HasFullFP16)
5934 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5937 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5942 EVT VT =
Op.getValueType();
5946 bool IsStrict =
Op->isStrictFPOpcode();
5947 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5949 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5959 MakeLibCallOptions CallOptions;
5962 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5963 CallOptions, Loc, Chain);
5973 Loc,
Op.getValueType(), SrcVal);
5982 EVT VT =
Op.getValueType();
5983 EVT ToVT = cast<VTSDNode>(
Op.getOperand(1))->getVT();
5984 EVT FromVT =
Op.getOperand(0).getValueType();
5986 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5988 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5989 Subtarget->hasFP64())
5991 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5992 Subtarget->hasFullFP16())
5994 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5995 Subtarget->hasMVEFloatOps())
5997 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5998 Subtarget->hasMVEFloatOps())
6001 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
6018 EVT VT =
Op.getValueType();
6021 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
6027 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
6028 Op.getOperand(0).getValueType() == MVT::v8i16) &&
6029 "Invalid type for custom lowering!");
6034 if (VT == MVT::v4f32)
6035 DestVecType = MVT::v4i32;
6036 else if (VT == MVT::v4f16 && HasFullFP16)
6037 DestVecType = MVT::v4i16;
6038 else if (VT == MVT::v8f16 && HasFullFP16)
6039 DestVecType = MVT::v8i16;
6045 switch (
Op.getOpcode()) {
6057 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
6062 EVT VT =
Op.getValueType();
6065 if (isUnsupportedFloatingType(VT)) {
6073 MakeLibCallOptions CallOptions;
6075 CallOptions,
SDLoc(
Op)).first;
6086 EVT VT =
Op.getValueType();
6090 bool UseNEON = !InGPR && Subtarget->hasNEON();
6097 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
6104 if (SrcVT == MVT::f32) {
6110 }
else if (VT == MVT::f32)
6126 if (VT == MVT::f32) {
6138 if (SrcVT == MVT::f64)
6147 if (VT == MVT::f32) {
6171 EVT VT =
Op.getValueType();
6173 unsigned Depth =
Op.getConstantOperandVal(0);
6175 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
6194 EVT VT =
Op.getValueType();
6196 unsigned Depth =
Op.getConstantOperandVal(0);
6210 .
Case(
"sp", ARM::SP)
6225 assert(
N->getValueType(0) == MVT::i64
6226 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
6229 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
6269 const APInt &APIntIndex = Index->getAPIntValue();
6271 NewIndex *= APIntIndex;
6301 EVT SrcVT =
Op.getValueType();
6302 EVT DstVT =
N->getValueType(0);
6304 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
6305 (DstVT == MVT::f16 || DstVT == MVT::bf16))
6309 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
6310 (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
6311 if (Subtarget->hasFullFP16() && !Subtarget->hasBF16())
6318 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
6322 if (SrcVT == MVT::i64 && TLI.
isTypeLegal(DstVT)) {
6334 if (DstVT == MVT::i64 && TLI.
isTypeLegal(SrcVT)) {
6371 EVT VT =
Op.getValueType();
6389 SDValue LoBigShift = DAG.
getNode(Opc, dl, VT, ShOpHi, ExtraShAmt);
6397 ? DAG.
getNode(Opc, dl, VT, ShOpHi,
6414 EVT VT =
Op.getValueType();
6456 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6508 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6536 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6566 EVT VT =
N->getValueType(0);
6567 if (VT.
isVector() && ST->hasNEON()) {
6576 if (ElemTy == MVT::i8) {
6584 if ((ElemTy == MVT::i16 || ElemTy == MVT::i32) &&
6599 if (ElemTy == MVT::i64) {
6612 if (!ST->hasV6T2Ops())
6621 EVT VT =
N->getValueType(0);
6624 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6625 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6626 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6627 "Unexpected type for custom ctpop lowering");
6635 unsigned EltSize = 8;
6658 Op =
Op.getOperand(0);
6660 APInt SplatBits, SplatUndef;
6661 unsigned SplatBitSize;
6664 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6666 SplatBitSize > ElementBits)
6677 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6681 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6692 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6697 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6698 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6707 EVT VT =
N->getValueType(0);
6729 "unexpected vector shift opcode");
6731 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6732 unsigned VShiftOpc =
6734 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6740 EVT ShiftVT =
N->getOperand(1).getValueType();
6743 unsigned VShiftOpc =
6745 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6750 EVT VT =
N->getValueType(0);
6759 "Unknown shift to lower!");
6761 unsigned ShOpc =
N->getOpcode();
6762 if (ST->hasMVEIntegerOps()) {
6792 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6806 if (ST->isThumb1Only())
6811 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6827 bool Invert =
false;
6834 EVT VT =
Op.getValueType();
6842 assert(ST->hasMVEIntegerOps() &&
6843 "No hardware support for integer vector comparison!");
6845 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6870 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6880 switch (SetCCOpcode) {
6884 if (ST->hasMVEFloatOps()) {
6887 Invert =
true; [[fallthrough]];
6892 case ISD::SETLT: Swap =
true; [[fallthrough]];
6896 case ISD::SETLE: Swap =
true; [[fallthrough]];
6912 Result = DAG.
getNOT(dl, Result, VT);
6915 case ISD::SETUO: Invert =
true; [[fallthrough]];
6924 Result = DAG.
getNOT(dl, Result, VT);
6930 switch (SetCCOpcode) {
6933 if (ST->hasMVEIntegerOps()) {
6936 Invert =
true; [[fallthrough]];
6939 case ISD::SETLT: Swap =
true; [[fallthrough]];
6941 case ISD::SETLE: Swap =
true; [[fallthrough]];
6950 if (ST->hasNEON() && Opc ==
ARMCC::EQ) {
6966 Result = DAG.
getNOT(dl, Result, VT);
7000 Result = DAG.
getNOT(dl, Result, VT);
7012 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
7039 unsigned OpCmode, Imm;
7050 switch (SplatBitSize) {
7055 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
7058 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
7063 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
7064 if ((SplatBits & ~0xff) == 0) {
7070 if ((SplatBits & ~0xff00) == 0) {
7073 Imm = SplatBits >> 8;
7083 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
7084 if ((SplatBits & ~0xff) == 0) {
7090 if ((SplatBits & ~0xff00) == 0) {
7093 Imm = SplatBits >> 8;
7096 if ((SplatBits & ~0xff0000) == 0) {
7099 Imm = SplatBits >> 16;
7102 if ((SplatBits & ~0xff000000) == 0) {
7105 Imm = SplatBits >> 24;
7112 if ((SplatBits & ~0xffff) == 0 &&
7113 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
7116 Imm = SplatBits >> 8;
7124 if ((SplatBits & ~0xffffff) == 0 &&
7125 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
7128 Imm = SplatBits >> 16;
7144 unsigned ImmMask = 1;
7146 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
7147 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
7149 }
else if ((SplatBits & BitMask) != 0) {
7158 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
7172 EVT VT =
Op.getValueType();
7173 bool IsDouble = (VT == MVT::f64);
7179 if (
ST->genExecuteOnly()) {
7181 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
7182 "Unexpected architecture");
7205 if (!
ST->hasVFP3Base())
7210 if (IsDouble && !Subtarget->hasFP64())
7217 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
7235 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
7244 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
7298 unsigned ExpectedElt = Imm;
7299 for (
unsigned i = 1; i < NumElts; ++i) {
7303 if (ExpectedElt == NumElts)
7306 if (M[i] < 0)
continue;
7307 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7315 bool &ReverseVEXT,
unsigned &Imm) {
7317 ReverseVEXT =
false;
7328 unsigned ExpectedElt = Imm;
7329 for (
unsigned i = 1; i < NumElts; ++i) {
7333 if (ExpectedElt == NumElts * 2) {
7338 if (M[i] < 0)
continue;
7339 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7354 return VT == MVT::v8i8 && M.size() == 8;
7359 if (Mask.size() == Elements * 2)
7360 return Index / Elements;
7361 return Mask[Index] == 0 ? 0 : 1;
7391 if (M.size() != NumElts && M.size() != NumElts*2)
7399 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7401 for (
unsigned j = 0; j < NumElts; j += 2) {
7402 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7403 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + NumElts + WhichResult))
7408 if (M.size() == NumElts*2)
7423 if (M.size() != NumElts && M.size() != NumElts*2)
7426 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7428 for (
unsigned j = 0; j < NumElts; j += 2) {
7429 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7430 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + WhichResult))
7435 if (M.size() == NumElts*2)
7455 if (M.size() != NumElts && M.size() != NumElts*2)
7458 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7460 for (
unsigned j = 0; j < NumElts; ++j) {
7461 if (M[i+j] >= 0 && (
unsigned) M[i+j] != 2 * j + WhichResult)
7466 if (M.size() == NumElts*2)
7485 if (M.size() != NumElts && M.size() != NumElts*2)
7488 unsigned Half = NumElts / 2;
7489 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7491 for (
unsigned j = 0; j < NumElts; j += Half) {
7492 unsigned Idx = WhichResult;
7493 for (
unsigned k = 0; k < Half; ++k) {
7494 int MIdx = M[i + j + k];
7495 if (MIdx >= 0 && (
unsigned) MIdx !=
Idx)
7502 if (M.size() == NumElts*2)
7526 if (M.size() != NumElts && M.size() != NumElts*2)
7529 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7531 unsigned Idx = WhichResult * NumElts / 2;
7532 for (
unsigned j = 0; j < NumElts; j += 2) {
7533 if ((M[i+j] >= 0 && (
unsigned) M[i+j] !=
Idx) ||
7534 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] !=
Idx + NumElts))
7540 if (M.size() == NumElts*2)
7559 if (M.size() != NumElts && M.size() != NumElts*2)
7562 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7564 unsigned Idx = WhichResult * NumElts / 2;
7565 for (
unsigned j = 0; j < NumElts; j += 2) {
7566 if ((M[i+j] >= 0 && (
unsigned) M[i+j] !=
Idx) ||
7567 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] !=
Idx))
7573 if (M.size() == NumElts*2)
7586 unsigned &WhichResult,
7589 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7591 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7593 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7611 if (NumElts != M.size())
7615 for (
unsigned i = 0; i != NumElts; ++i)
7616 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7625 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7633 int Ofs = Top ? 1 : 0;
7634 int Upper = SingleSource ? 0 : NumElts;
7635 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7636 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7638 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7647 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7656 unsigned Offset = Top ? 0 : 1;
7657 unsigned N = SingleSource ? 0 : NumElts;
7658 for (
unsigned i = 0; i < NumElts; i += 2) {
7659 if (M[i] >= 0 && M[i] != (
int)i)
7661 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7670 if (NumElts != M.size())
7678 unsigned Off0 = rev ? NumElts / 2 : 0;
7679 unsigned Off1 = rev ? 0 : NumElts / 2;
7680 for (
unsigned i = 0; i < NumElts; i += 2) {
7681 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7683 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7699 if (!ST->hasMVEFloatOps())
7704 if (VT != MVT::v8f16)
7725 for (
unsigned i = 1; i < 4; i++) {
7752 if (!ST->hasMVEFloatOps())
7757 if (VT != MVT::v4f32)
7773 for (
unsigned i = 1; i < 4; i++) {
7794 if (!isa<ConstantSDNode>(
N))
7796 Val =
N->getAsZExtVal();
7798 if (ST->isThumb1Only()) {
7799 if (Val <= 255 || ~Val <= 255)
7811 EVT VT =
Op.getValueType();
7813 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7817 unsigned BitsPerBool;
7821 }
else if (NumElts == 4) {
7824 }
else if (NumElts == 8) {
7827 }
else if (NumElts == 16) {
7836 if (!isa<ConstantSDNode>(FirstOp) &&
7838 return U.get().isUndef() || U.get() == FirstOp;
7846 unsigned Bits32 = 0;
7847 for (
unsigned i = 0; i < NumElts; ++i) {
7849 if (!isa<ConstantSDNode>(V) && !V.isUndef())
7851 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7853 Bits32 |= BoolMask << (i * BitsPerBool);
7859 for (
unsigned i = 0; i < NumElts; ++i) {
7861 if (isa<ConstantSDNode>(V) || V.isUndef())
7872 if (!ST->hasMVEIntegerOps())
7876 EVT VT =
Op.getValueType();
7886 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7890 for (
unsigned I = 2;
I < NumElts;
I++) {
7906 switch (
N->getOpcode()) {
7917 return N->getOperand(1).getNode() ==
Op;
7919 switch (
N->getConstantOperandVal(0)) {
7920 case Intrinsic::arm_mve_add_predicated:
7921 case Intrinsic::arm_mve_mul_predicated:
7922 case Intrinsic::arm_mve_qadd_predicated:
7923 case Intrinsic::arm_mve_vhadd:
7924 case Intrinsic::arm_mve_hadd_predicated:
7925 case Intrinsic::arm_mve_vqdmulh:
7926 case Intrinsic::arm_mve_qdmulh_predicated:
7927 case Intrinsic::arm_mve_vqrdmulh:
7928 case Intrinsic::arm_mve_qrdmulh_predicated:
7929 case Intrinsic::arm_mve_vqdmull:
7930 case Intrinsic::arm_mve_vqdmull_predicated:
7932 case Intrinsic::arm_mve_sub_predicated:
7933 case Intrinsic::arm_mve_qsub_predicated:
7934 case Intrinsic::arm_mve_vhsub:
7935 case Intrinsic::arm_mve_hsub_predicated:
7936 return N->getOperand(2).getNode() ==
Op;
7951 EVT VT =
Op.getValueType();
7959 APInt SplatBits, SplatUndef;
7960 unsigned SplatBitSize;
7962 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7969 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7971 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7972 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7973 : SplatBitSize == 16 ? MVT::v8i16
7980 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7981 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7986 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7994 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7996 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
8004 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
8014 if (
ST->hasMVEIntegerOps() &&
8015 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
8016 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
8017 : SplatBitSize == 16 ? MVT::v8i16
8034 bool isOnlyLowElement =
true;
8035 bool usesOnlyOneValue =
true;
8036 bool hasDominantValue =
false;
8043 for (
unsigned i = 0; i < NumElts; ++i) {
8048 isOnlyLowElement =
false;
8049 if (!isa<ConstantFPSDNode>(V) && !isa<ConstantSDNode>(V))
8052 unsigned &Count = ValueCounts[
V];
8055 if (++Count > (NumElts / 2)) {
8056 hasDominantValue =
true;
8060 if (ValueCounts.
size() != 1)
8061 usesOnlyOneValue =
false;
8062 if (!
Value.getNode() && !ValueCounts.
empty())
8065 if (ValueCounts.
empty())
8077 if (hasDominantValue && EltSize <= 32) {
8088 (constIndex = dyn_cast<ConstantSDNode>(
Value->getOperand(1)))) {
8093 if (VT !=
Value->getOperand(0).getValueType()) {
8106 if (!usesOnlyOneValue) {
8109 for (
unsigned I = 0;
I < NumElts; ++
I) {
8124 assert(FVT == MVT::f32 || FVT == MVT::f16);
8125 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
8126 for (
unsigned i = 0; i < NumElts; ++i)
8131 Val = LowerBUILD_VECTOR(Val, DAG, ST);
8135 if (usesOnlyOneValue) {
8162 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
8182 if (EltSize >= 32) {
8188 for (
unsigned i = 0; i < NumElts; ++i)
8202 for (
unsigned i = 0 ; i < NumElts; ++i) {
8221 EVT VT =
Op.getValueType();
8224 struct ShuffleSourceInfo {
8226 unsigned MinElt = std::numeric_limits<unsigned>::max();
8227 unsigned MaxElt = 0;
8237 int WindowScale = 1;
8239 ShuffleSourceInfo(
SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
8241 bool operator ==(
SDValue OtherVec) {
return Vec == OtherVec; }
8247 for (
unsigned i = 0; i < NumElts; ++i) {
8255 }
else if (!isa<ConstantSDNode>(
V.getOperand(1))) {
8262 SDValue SourceVec =
V.getOperand(0);
8264 if (Source == Sources.
end())
8268 unsigned EltNo =
V.getConstantOperandVal(1);
8275 if (Sources.
size() > 2)
8281 for (
auto &Source : Sources) {
8282 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
8283 if (SrcEltTy.
bitsLT(SmallestEltTy))
8284 SmallestEltTy = SrcEltTy;
8286 unsigned ResMultiplier =
8294 for (
auto &Src : Sources) {
8295 EVT SrcVT = Src.ShuffleVec.getValueType();
8299 if (SrcVTSize == VTSize)
8308 if (SrcVTSize < VTSize) {
8309 if (2 * SrcVTSize != VTSize)
8315 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
8319 if (SrcVTSize != 2 * VTSize)
8322 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
8327 if (Src.MinElt >= NumSrcElts) {
8332 Src.WindowBase = -NumSrcElts;
8333 }
else if (Src.MaxElt < NumSrcElts) {
8350 Src.WindowBase = -Src.MinElt;
8357 for (
auto &Src : Sources) {
8358 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
8359 if (SrcEltTy == SmallestEltTy)
8364 Src.WindowBase *= Src.WindowScale;
8369 for (
auto Src : Sources)
8370 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
8378 if (
Entry.isUndef())
8382 int EltNo = cast<ConstantSDNode>(
Entry.getOperand(1))->getSExtValue();
8387 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
8390 int LanesDefined = BitsDefined / BitsPerShuffleLane;
8394 int *LaneMask = &
Mask[i * ResMultiplier];
8396 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
8397 ExtractBase += NumElts * (Src - Sources.begin());
8398 for (
int j = 0;
j < LanesDefined; ++
j)
8399 LaneMask[j] = ExtractBase + j;
8405 assert(Sources.size() <= 2 &&
"Too many sources!");
8408 for (
unsigned i = 0; i < Sources.size(); ++i)
8437 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8457 unsigned PFIndexes[4];
8458 for (
unsigned i = 0; i != 4; ++i) {
8462 PFIndexes[i] = M[i];
8466 unsigned PFTableIndex =
8467 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8469 unsigned Cost = (PFEntry >> 30);
8475 bool ReverseVEXT, isV_UNDEF;
8476 unsigned Imm, WhichResult;
8479 if (EltSize >= 32 ||
8486 else if (Subtarget->hasNEON() &&
8491 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8494 else if (Subtarget->hasMVEIntegerOps() &&
8498 else if (Subtarget->hasMVEIntegerOps() &&
8512 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8513 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8514 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8517 if (LHSID == (1*9+2)*9+3)
return LHS;
8518 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8575 for (
int I : ShuffleMask)
8578 if (V2.getNode()->isUndef())
8588 EVT VT =
Op.getValueType();
8590 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8591 "Expect an v8i16/v16i8 type");
8597 std::vector<int> NewMask;
8601 NewMask.push_back(i);
8641 if (VT != MVT::v16i1)
8657 EVT VT =
Op.getValueType();
8661 assert(ST->hasMVEIntegerOps() &&
8662 "No support for vector shuffle of boolean predicates");
8688 "Expected identical vector type in expanded i1 shuffle!");
8692 PredAsVector2, ShuffleMask);
8697 if (VT == MVT::v2i1) {
8714 EVT VT =
Op.getValueType();
8718 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8719 "Unexpected vector type");
8721 int QuarterSize = NumElts / 4;
8730 for (
int i = 0; i <
Length; i++) {
8731 if (ShuffleMask[Start + i] >= 0) {
8732 if (ShuffleMask[Start + i] %
Length != i)
8734 MovIdx = ShuffleMask[Start + i] /
Length;
8742 for (
int i = 1; i <
Length; i++) {
8743 if (ShuffleMask[Start + i] >= 0 &&
8744 (ShuffleMask[Start + i] /
Length != MovIdx ||
8745 ShuffleMask[Start + i] %
Length != i))
8751 for (
int Part = 0; Part < 4; ++Part) {
8753 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8757 Input =
Op->getOperand(1);
8767 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8772 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8774 for (
int Part = 0; Part < 4; ++Part)
8775 for (
int i = 0; i < QuarterSize; i++)
8777 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8779 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8782 for (
int Part = 0; Part < 4; ++Part)
8798 EVT VT =
Op.getValueType();
8810 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8814 if (Mask[i] != i + BaseOffset) {
8815 if (OffElement == -1)
8821 return NonUndef > 2 && OffElement != -1;
8825 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8827 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8838 ShuffleMask[OffElement] < (
int)NumElts ? V1 : V2,
8849 EVT VT =
Op.getValueType();
8853 if (ST->hasMVEIntegerOps() && EltSize == 1)
8864 if (EltSize <= 32) {
8868 if (Lane == -1) Lane = 0;
8879 bool IsScalarToVector =
true;
8882 IsScalarToVector =
false;
8885 if (IsScalarToVector)
8892 bool ReverseVEXT =
false;
8894 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) {
8918 unsigned WhichResult = 0;
8919 bool isV_UNDEF =
false;
8920 if (ST->hasNEON()) {
8922 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8929 if (ST->hasMVEIntegerOps()) {
8964 }) &&
"Unexpected shuffle index into UNDEF operand!");
8967 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8970 assert((WhichResult == 0) &&
8971 "In-place shuffle of concat can only have one result!");
8980 if (ST->hasMVEIntegerOps() && EltSize <= 32) {
8984 for (
bool Top : {
false,
true}) {
8985 for (
bool SingleSource : {
false,
true}) {
8986 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8991 SingleSource ? V1 : V2);
9007 unsigned PFIndexes[4];
9008 for (
unsigned i = 0; i != 4; ++i) {
9009 if (ShuffleMask[i] < 0)
9012 PFIndexes[i] = ShuffleMask[i];
9016 unsigned PFTableIndex =
9017 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
9019 unsigned Cost = (PFEntry >> 30);
9025 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
9026 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
9036 if (EltSize >= 32) {
9044 for (
unsigned i = 0; i < NumElts; ++i) {
9045 if (ShuffleMask[i] < 0)
9049 ShuffleMask[i] < (
int)NumElts ? V1 : V2,
9057 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
9061 if (ST->hasNEON() && VT == MVT::v8i8)
9065 if (ST->hasMVEIntegerOps())
9074 EVT VecVT =
Op.getOperand(0).getValueType();
9077 assert(ST->hasMVEIntegerOps() &&
9078 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
9082 unsigned Lane =
Op.getConstantOperandVal(2);
9083 unsigned LaneWidth =
9085 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
9097 if (!isa<ConstantSDNode>(Lane))
9103 if (Subtarget->hasMVEIntegerOps() &&
9104 Op.getValueType().getScalarSizeInBits() == 1)
9128 IVecIn, IElt, Lane);
9137 EVT VecVT =
Op.getOperand(0).getValueType();
9140 assert(ST->hasMVEIntegerOps() &&
9141 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
9145 unsigned Lane =
Op.getConstantOperandVal(1);
9146 unsigned LaneWidth =
9157 if (!isa<ConstantSDNode>(Lane))
9177 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
9178 "Unexpected custom CONCAT_VECTORS lowering");
9180 "Unexpected custom CONCAT_VECTORS lowering");
9181 assert(ST->hasMVEIntegerOps() &&
9182 "CONCAT_VECTORS lowering only supported for MVE");
9186 EVT Op2VT = V2.getValueType();
9187 assert(Op1VT == Op2VT &&
"Operand types don't match!");
9188 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
9189 "Unexpected i1 concat operations!");
9202 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
9216 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
9217 EVT NewVT = NewV.getValueType();
9218 EVT ConcatVT = ConVec.getValueType();
9219 unsigned ExtScale = 1;
9220 if (NewVT == MVT::v2f64) {
9234 ConVec = ExtractInto(NewV1, ConVec, j);
9235 ConVec = ExtractInto(NewV2, ConVec, j);
9245 while (ConcatOps.
size() > 1) {
9246 for (
unsigned I = 0, E = ConcatOps.
size();
I != E;
I += 2) {
9249 ConcatOps[
I / 2] = ConcatPair(V1, V2);
9253 return ConcatOps[0];
9258 EVT VT =
Op->getValueType(0);
9265 "unexpected CONCAT_VECTORS");
9286 EVT VT =
Op.getValueType();
9289 unsigned Index = V2->getAsZExtVal();
9292 "Unexpected custom EXTRACT_SUBVECTOR lowering");
9293 assert(ST->hasMVEIntegerOps() &&
9294 "EXTRACT_SUBVECTOR lowering only supported for MVE");
9304 EVT SubVT = MVT::v4i32;
9306 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j += 2) {
9321 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j++) {
9337 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
9338 EVT VT =
N->getValueType(0);
9339 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
9340 "Expected a vector i1 type!");
9342 EVT FromVT =
Op.getValueType();
9353 if (!Subtarget->hasMVEIntegerOps())
9356 EVT ToVT =
N->getValueType(0);
9399 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
9401 EVT FromVT =
N->getOperand(0).getValueType();
9402 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9413 if (!Subtarget->hasMVEIntegerOps())
9418 EVT ToVT =
N->getValueType(0);
9419 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9422 EVT FromVT =
Op.getValueType();
9423 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9434 SDValue Ext1 = Ext.getValue(1);
9437 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9438 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9450 EVT VT =
N->getValueType(0);
9452 SDNode *BVN =
N->getOperand(0).getNode();
9457 unsigned HiElt = 1 - LoElt;
9462 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9478 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9479 SDNode *Elt =
N->getOperand(i).getNode();
9482 unsigned HalfSize = EltSize / 2;
9484 if (!
isIntN(HalfSize,
C->getSExtValue()))
9487 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9526 switch (OrigSimpleTy) {
9542 unsigned ExtOpcode) {
9565 if (ExtendedTy == LD->getMemoryVT())
9566 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9567 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9568 LD->getMemOperand()->getFlags());
9574 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9575 LD->getMemoryVT(), LD->getAlign(),
9576 LD->getMemOperand()->getFlags());
9589 N->getOperand(0)->getValueType(0),
9595 "Expected extending load");
9601 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9610 SDNode *BVN =
N->getOperand(0).getNode();
9612 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9620 EVT VT =
N->getValueType(0);
9626 for (
unsigned i = 0; i != NumElts; ++i) {
9627 const APInt &CInt =
N->getConstantOperandAPInt(i);
9636 unsigned Opcode =
N->getOpcode();
9638 SDNode *N0 =
N->getOperand(0).getNode();
9639 SDNode *N1 =
N->getOperand(1).getNode();
9647 unsigned Opcode =
N->getOpcode();
9649 SDNode *N0 =
N->getOperand(0).getNode();
9650 SDNode *N1 =
N->getOperand(1).getNode();
9660 EVT VT =
Op.getValueType();
9662 "unexpected type for custom-lowering ISD::MUL");
9663 SDNode *N0 =
Op.getOperand(0).getNode();
9664 SDNode *N1 =
Op.getOperand(1).getNode();
9665 unsigned NewOpc = 0;
9669 if (isN0SExt && isN1SExt)
9674 if (isN0ZExt && isN1ZExt)
9676 else if (isN1SExt || isN1ZExt) {
9693 if (VT == MVT::v2i64)
9710 "unexpected types for extended operands to VMULL");
9711 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9746 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9780 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9783 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9804 EVT VT =
Op.getValueType();
9805 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9806 "unexpected type for custom-lowering ISD::SDIV");
9813 if (VT == MVT::v8i8) {
9841 EVT VT =
Op.getValueType();
9842 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9843 "unexpected type for custom-lowering ISD::UDIV");
9850 if (VT == MVT::v8i8) {
9889 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9892 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9896 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9917 EVT VT =
N->getValueType(0);
9931 Op.getOperand(1), Carry);
9945 Op.getOperand(1), Carry);
9978 bool ShouldUseSRet = Subtarget->
isAPCS_ABI();
9980 if (ShouldUseSRet) {
9990 Entry.IsSExt =
false;
9991 Entry.IsZExt =
false;
9992 Entry.IsSRet =
true;
9993 Args.push_back(Entry);
10000 Entry.IsSExt =
false;
10001 Entry.IsZExt =
false;
10002 Args.push_back(Entry);
10005 (ArgVT == MVT::f64) ? RTLIB::SINCOS_STRET_F64 : RTLIB::SINCOS_STRET_F32;
10015 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
10017 if (!ShouldUseSRet)
10018 return CallResult.first;
10037 EVT VT =
Op.getValueType();
10038 assert((VT == MVT::i32 || VT == MVT::i64) &&
10039 "unexpected type for custom lowering DIV");
10045 const char *
Name =
nullptr;
10047 Name = (VT == MVT::i32) ?
"__rt_sdiv" :
"__rt_sdiv64";
10049 Name = (VT == MVT::i32) ?
"__rt_udiv" :
"__rt_udiv64";
10055 for (
auto AI : {1, 0}) {
10057 Arg.Node =
Op.getOperand(AI);
10058 Arg.Ty = Arg.Node.getValueType().getTypeForEVT(*DAG.
getContext());
10059 Args.push_back(Arg);
10062 CallLoweringInfo CLI(DAG);
10066 ES, std::move(Args));
10076ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
10084 const bool MinSize =
ST.hasMinSize();
10085 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
10086 :
ST.hasDivideInARMMode();
10090 if (
N->getOperand(0).getValueType().isVector())
10095 if (!(MinSize && HasDivide))
10108 if (Divisor.
sgt(128))
10116 assert(
Op.getValueType() == MVT::i32 &&
10117 "unexpected type for custom lowering DIV");
10123 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
10129 if (
N->getValueType(0) == MVT::i32)
10137void ARMTargetLowering::ExpandDIV_Windows(
10143 assert(
Op.getValueType() == MVT::i64 &&
10144 "unexpected type for custom lowering DIV");
10161 EVT MemVT = LD->getMemoryVT();
10162 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10163 MemVT == MVT::v16i1) &&
10164 "Expected a predicate type!");
10165 assert(MemVT ==
Op.getValueType());
10167 "Expected a non-extending load");
10168 assert(LD->isUnindexed() &&
"Expected a unindexed load");
10182 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
10184 LD->getMemOperand());
10191 if (MemVT != MVT::v16i1)
10200 EVT MemVT =
LD->getMemoryVT();
10201 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
10203 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10209 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
10219 EVT MemVT = ST->getMemoryVT();
10220 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10221 MemVT == MVT::v16i1) &&
10222 "Expected a predicate type!");
10223 assert(MemVT == ST->getValue().getValueType());
10224 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
10225 assert(ST->isUnindexed() &&
"Expected a unindexed store");
10230 SDValue Build = ST->getValue();
10231 if (MemVT != MVT::v16i1) {
10250 ST->getChain(), dl, GRP, ST->getBasePtr(),
10252 ST->getMemOperand());
10258 EVT MemVT = ST->getMemoryVT();
10259 assert(ST->isUnindexed() &&
"Stores should be unindexed at this point.");
10261 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10277 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
10278 MemVT, ST->getMemOperand());
10279 }
else if (Subtarget->hasMVEIntegerOps() &&
10280 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10281 MemVT == MVT::v16i1))) {
10296 MVT VT =
Op.getSimpleValueType();
10298 SDValue PassThru =
N->getPassThru();
10309 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
10310 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
10311 N->getExtensionType(),
N->isExpandingLoad());
10316 if (!PassThru.
isUndef() && !PassThruIsCastZero)
10323 if (!ST->hasMVEIntegerOps())
10327 unsigned BaseOpcode = 0;
10328 switch (
Op->getOpcode()) {
10344 unsigned NumActiveLanes = NumElts;
10346 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10347 NumActiveLanes == 2) &&
10348 "Only expected a power 2 vector size");
10352 while (NumActiveLanes > 4) {
10355 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
10356 NumActiveLanes /= 2;
10360 if (NumActiveLanes == 4) {
10370 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10371 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
10372 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
10378 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10382 if (EltVT !=
Op->getValueType(0))
10389 if (!ST->hasMVEFloatOps())
10396 if (!ST->hasNEON())
10404 unsigned PairwiseIntrinsic = 0;
10405 switch (
Op->getOpcode()) {
10409 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
10412 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
10415 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
10418 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
10424 unsigned NumActiveLanes = NumElts;
10426 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10427 NumActiveLanes == 2) &&
10428 "Only expected a power 2 vector size");
10434 VT =
Lo.getValueType();
10436 NumActiveLanes /= 2;
10440 while (NumActiveLanes > 1) {
10442 NumActiveLanes /= 2;
10449 if (EltVT !=
Op.getValueType()) {
10450 unsigned Extend = 0;
10451 switch (
Op->getOpcode()) {
10463 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10485 SDValue Ops[] = {
N->getOperand(0),
10495 DAG.
getVTList(MVT::i32, MVT::Other), Ops);
10508 const SDValue Ops[] = {RegClass, V0, SubReg0, V1, SubReg1};
10510 DAG.
getMachineNode(TargetOpcode::REG_SEQUENCE, dl, MVT::Untyped, Ops), 0);
10514 SDLoc dl(V.getNode());
10515 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10525 assert(
N->getValueType(0) == MVT::i64 &&
10526 "AtomicCmpSwap on types less than 64 should be legal");
10535 ARM::CMP_SWAP_64,
SDLoc(
N),
10536 DAG.
getVTList(MVT::Untyped, MVT::Untyped, MVT::Other), Ops);
10555 EVT VT =
Op.getValueType();
10564 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10566 DAG,
LHS.getValueType(), LHS, RHS,
CC, dl, LHS, RHS, Chain, IsSignaling);
10567 if (!
RHS.getNode()) {
10582 SDValue Cmp = getVFPCmp(LHS, RHS, DAG, dl, IsSignaling);
10583 SDValue Result = getCMOV(dl, VT, False, True, ARMcc, Cmp, DAG);
10585 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10586 Result = getCMOV(dl, VT, Result, True, ARMcc, Cmp, DAG);
10603 MakeLibCallOptions CallOptions;
10604 MVT SVT =
Op.getOperand(0).getSimpleValueType();
10607 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
10613 switch (
Op.getOpcode()) {
10645 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10649 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10650 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10672 return LowerSET_FPMODE(
Op, DAG);
10674 return LowerRESET_FPMODE(
Op, DAG);
10678 return LowerDIV_Windows(
Op, DAG,
true);
10682 return LowerDIV_Windows(
Op, DAG,
false);
10689 return LowerSignedALUO(
Op, DAG);
10692 return LowerUnsignedALUO(
Op, DAG);
10726 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10735 return LowerSPONENTRY(
Op, DAG);
10737 return LowerFP_TO_BF16(
Op, DAG);
10744 unsigned IntNo =
N->getConstantOperandVal(0);
10746 if (IntNo == Intrinsic::arm_smlald)
10748 else if (IntNo == Intrinsic::arm_smlaldx)
10750 else if (IntNo == Intrinsic::arm_smlsld)
10752 else if (IntNo == Intrinsic::arm_smlsldx)
10759 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(3), dl, MVT::i32, MVT::i32);
10763 N->getOperand(1),
N->getOperand(2),
10775 switch (
N->getOpcode()) {
10782 Res = ExpandBITCAST(
N, DAG, Subtarget);
10791 Res = LowerREM(
N, DAG);
10795 Res = LowerDivRem(
SDValue(
N, 0), DAG);
10849 "ROPI/RWPI not currently supported with SjLj");
10858 bool isThumb = Subtarget->isThumb();
10859 bool isThumb2 = Subtarget->
isThumb2();
10862 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10868 : &ARM::GPRRegClass;
10886 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10892 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10898 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10916 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10921 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10926 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10931 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10937 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
10952 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10958 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10982 : &ARM::GPRnopcRegClass;
10987 unsigned MaxCSNum = 0;
10995 if (!
II.isEHLabel())
10999 if (!MF->hasCallSiteLandingPad(
Sym))
continue;
11002 for (
unsigned Idx : CallSiteIdxs) {
11003 CallSiteNumToLPad[
Idx].push_back(&BB);
11004 MaxCSNum = std::max(MaxCSNum,
Idx);
11011 std::vector<MachineBasicBlock*> LPadList;
11014 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
11017 LPadList.push_back(
MBB);
11022 assert(!LPadList.empty() &&
11023 "No landing pad destinations for the dispatch jump table!");
11037 unsigned trap_opcode;
11038 if (Subtarget->isThumb())
11039 trap_opcode = ARM::tTRAP;
11041 trap_opcode = Subtarget->useNaClTrap() ? ARM::TRAPNaCl : ARM::TRAP;
11050 MF->insert(MF->end(), DispatchBB);
11051 MF->insert(MF->end(), DispContBB);
11052 MF->insert(MF->end(), TrapBB);
11056 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
11063 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
11075 unsigned NumLPads = LPadList.size();
11077 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11078 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
11084 if (NumLPads < 256) {
11085 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
11087 .
addImm(LPadList.size())
11090 Register VReg1 =
MRI->createVirtualRegister(TRC);
11091 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
11092 .
addImm(NumLPads & 0xFFFF)
11095 unsigned VReg2 = VReg1;
11096 if ((NumLPads & 0xFFFF0000) != 0) {
11097 VReg2 =
MRI->createVirtualRegister(TRC);
11098 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
11104 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
11110 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
11115 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11116 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
11120 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11121 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
11128 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
11132 }
else if (Subtarget->isThumb()) {
11133 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11134 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
11140 if (NumLPads < 256) {
11141 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
11148 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
11151 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
11154 Register VReg1 =
MRI->createVirtualRegister(TRC);
11155 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
11159 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
11165 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
11170 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
11171 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
11177 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11178 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
11182 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11183 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
11193 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
11194 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
11200 unsigned NewVReg6 = NewVReg5;
11201 if (IsPositionIndependent) {
11202 NewVReg6 =
MRI->createVirtualRegister(TRC);
11203 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
11210 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
11214 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11215 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
11221 if (NumLPads < 256) {
11222 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
11226 }
else if (Subtarget->hasV6T2Ops() && isUInt<16>(NumLPads)) {
11227 Register VReg1 =
MRI->createVirtualRegister(TRC);
11228 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
11229 .
addImm(NumLPads & 0xFFFF)
11232 unsigned VReg2 = VReg1;
11233 if ((NumLPads & 0xFFFF0000) != 0) {
11234 VReg2 =
MRI->createVirtualRegister(TRC);
11235 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
11241 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11248 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
11251 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
11254 Register VReg1 =
MRI->createVirtualRegister(TRC);
11255 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
11260 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11271 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11272 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
11277 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11278 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
11285 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
11286 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
11293 if (IsPositionIndependent) {
11294 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11299 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11308 if (SeenMBBs.
insert(CurMBB).second)
11320 while (!Successors.empty()) {
11329 BB->normalizeSuccProbs();
11336 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11337 if (!
II->isCall())
continue;
11341 OI =
II->operands_begin(), OE =
II->operands_end();
11343 if (!OI->isReg())
continue;
11344 DefRegs[OI->getReg()] =
true;
11349 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11350 unsigned Reg = SavedRegs[i];
11352 !ARM::tGPRRegClass.contains(Reg) &&
11353 !ARM::hGPRRegClass.contains(Reg))
11355 if (Subtarget->
isThumb1Only() && !ARM::tGPRRegClass.contains(Reg))
11357 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(Reg))
11370 MBBLPad->setIsEHPad(
false);
11373 MI.eraseFromParent();
11386static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11388 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11389 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11391 return LdSize == 4 ? ARM::tLDRi
11392 : LdSize == 2 ? ARM::tLDRHi
11393 : LdSize == 1 ? ARM::tLDRBi : 0;
11395 return LdSize == 4 ? ARM::t2LDR_POST
11396 : LdSize == 2 ? ARM::t2LDRH_POST
11397 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11398 return LdSize == 4 ? ARM::LDR_POST_IMM
11399 : LdSize == 2 ? ARM::LDRH_POST
11400 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11405static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11407 return StSize == 16 ? ARM::VST1q32wb_fixed
11408 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11410 return StSize == 4 ? ARM::tSTRi
11411 : StSize == 2 ? ARM::tSTRHi
11412 : StSize == 1 ? ARM::tSTRBi : 0;
11414 return StSize == 4 ? ARM::t2STR_POST
11415 : StSize == 2 ? ARM::t2STRH_POST
11416 : StSize == 1 ? ARM::t2STRB_POST : 0;
11417 return StSize == 4 ? ARM::STR_POST_IMM
11418 : StSize == 2 ? ARM::STRH_POST
11419 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11426 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11427 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11428 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11429 assert(LdOpc != 0 &&
"Should have a load opcode");
11436 }
else if (IsThumb1) {
11442 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11447 }
else if (IsThumb2) {
11467 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11468 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11469 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11470 assert(StOpc != 0 &&
"Should have a store opcode");
11472 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11477 }
else if (IsThumb1) {
11484 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11489 }
else if (IsThumb2) {
11490 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11496 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11517 unsigned SizeVal =
MI.getOperand(2).getImm();
11518 unsigned Alignment =
MI.getOperand(3).getImm();
11523 unsigned UnitSize = 0;
11528 bool IsThumb2 = Subtarget->
isThumb2();
11529 bool IsThumb = Subtarget->isThumb();
11531 if (Alignment & 1) {
11533 }
else if (Alignment & 2) {
11538 Subtarget->hasNEON()) {
11539 if ((Alignment % 16 == 0) && SizeVal >= 16)
11541 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11550 bool IsNeon = UnitSize >= 8;
11551 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11553 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11554 : UnitSize == 8 ? &ARM::DPRRegClass
11557 unsigned BytesLeft = SizeVal % UnitSize;
11558 unsigned LoopSize = SizeVal - BytesLeft;
11560 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11564 unsigned srcIn = src;
11565 unsigned destIn = dest;
11566 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11567 Register srcOut =
MRI.createVirtualRegister(TRC);
11568 Register destOut =
MRI.createVirtualRegister(TRC);
11569 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11571 IsThumb1, IsThumb2);
11573 IsThumb1, IsThumb2);
11581 for (
unsigned i = 0; i < BytesLeft; i++) {
11582 Register srcOut =
MRI.createVirtualRegister(TRC);
11583 Register destOut =
MRI.createVirtualRegister(TRC);
11584 Register scratch =
MRI.createVirtualRegister(TRC);
11586 IsThumb1, IsThumb2);
11588 IsThumb1, IsThumb2);
11592 MI.eraseFromParent();
11618 MF->
insert(It, loopMBB);
11619 MF->
insert(It, exitMBB);
11622 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11632 Register varEnd =
MRI.createVirtualRegister(TRC);
11634 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11637 }
else if (Subtarget->genExecuteOnly()) {
11638 assert(IsThumb &&
"Non-thumb expected to have used movt");
11643 const Constant *
C = ConstantInt::get(Int32Ty, LoopSize);
11674 Register varLoop =
MRI.createVirtualRegister(TRC);
11675 Register varPhi =
MRI.createVirtualRegister(TRC);
11676 Register srcLoop =
MRI.createVirtualRegister(TRC);
11677 Register srcPhi =
MRI.createVirtualRegister(TRC);
11678 Register destLoop =
MRI.createVirtualRegister(TRC);
11679 Register destPhi =
MRI.createVirtualRegister(TRC);
11687 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11693 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11695 IsThumb1, IsThumb2);
11697 IsThumb1, IsThumb2);
11701 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11709 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11718 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11727 auto StartOfExit = exitMBB->
begin();
11731 unsigned srcIn = srcLoop;
11732 unsigned destIn = destLoop;
11733 for (
unsigned i = 0; i < BytesLeft; i++) {
11734 Register srcOut =
MRI.createVirtualRegister(TRC);
11735 Register destOut =
MRI.createVirtualRegister(TRC);
11736 Register scratch =
MRI.createVirtualRegister(TRC);
11737 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11738 IsThumb1, IsThumb2);
11739 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11740 IsThumb1, IsThumb2);
11745 MI.eraseFromParent();
11757 "__chkstk is only supported on Windows");
11758 assert(Subtarget->
isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11778 switch (
TM.getCodeModel()) {
11820 MI.eraseFromParent();
11844 .
addReg(
MI.getOperand(0).getReg())
11852 MI.eraseFromParent();
11876 if (miI == BB->
end()) {
11878 if (Succ->isLiveIn(ARM::CPSR))
11884 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11896 Register AddDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11897 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11903 Register LsrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11904 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11910 Register TotalIterationsReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11911 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11914 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11915 .
addUse(TotalIterationsReg)
11922 return TotalIterationsReg;
11933 Register TotalIterationsReg,
bool IsMemcpy) {
11940 SrcPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11941 CurrSrcReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11942 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11950 Register DestPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11951 Register CurrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11952 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11959 Register LoopCounterPhiReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11960 Register RemainingLoopIterationsReg =
11961 MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11962 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11963 .
addUse(TotalIterationsReg)
11965 .
addUse(RemainingLoopIterationsReg)
11969 Register PredCounterPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11970 Register RemainingElementsReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11971 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11972 .
addUse(ElementCountReg)
11974 .
addUse(RemainingElementsReg)
11978 Register VccrReg =
MRI.createVirtualRegister(&ARM::VCCRRegClass);
11979 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11980 .
addUse(PredCounterPhiReg)
11985 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11986 .
addUse(PredCounterPhiReg)
11994 SrcValueReg =
MRI.createVirtualRegister(&ARM::MQPRRegClass);
11995 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
12004 SrcValueReg = OpSrcReg;
12006 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
12017 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
12018 .
addUse(LoopCounterPhiReg)
12021 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
12022 .
addUse(RemainingLoopIterationsReg)
12035 bool isThumb2 = Subtarget->
isThumb2();
12036 switch (
MI.getOpcode()) {
12043 case ARM::tLDR_postidx: {
12047 .
add(
MI.getOperand(2))
12048 .
add(
MI.getOperand(3))
12049 .
add(
MI.getOperand(4))
12050 .
add(
MI.getOperand(0))
12052 MI.eraseFromParent();
12056 case ARM::MVE_MEMCPYLOOPINST:
12057 case ARM::MVE_MEMSETLOOPINST: {
12087 Register OpDestReg =
MI.getOperand(0).getReg();
12088 Register OpSrcReg =
MI.getOperand(1).getReg();
12089 Register OpSizeReg =
MI.getOperand(2).getReg();
12109 if (TpExit == BB) {
12111 "block containing memcpy/memset Pseudo");
12124 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
12126 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
12141 MI.eraseFromParent();
12151 case ARM::t2STR_preidx:
12152 MI.setDesc(
TII->get(ARM::t2STR_PRE));
12154 case ARM::t2STRB_preidx:
12155 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
12157 case ARM::t2STRH_preidx:
12158 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
12161 case ARM::STRi_preidx:
12162 case ARM::STRBi_preidx: {
12163 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
12164 : ARM::STRB_PRE_IMM;
12166 unsigned Offset =
MI.getOperand(4).getImm();
12174 .
add(
MI.getOperand(0))
12175 .
add(
MI.getOperand(1))
12176 .
add(
MI.getOperand(2))
12178 .
add(
MI.getOperand(5))
12179 .
add(
MI.getOperand(6))
12181 MI.eraseFromParent();
12184 case ARM::STRr_preidx:
12185 case ARM::STRBr_preidx:
12186 case ARM::STRH_preidx: {
12188 switch (
MI.getOpcode()) {
12190 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
12191 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
12192 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
12197 MI.eraseFromParent();
12201 case ARM::tMOVCCr_pseudo: {
12219 F->insert(It, copy0MBB);
12220 F->insert(It, sinkMBB);
12223 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12229 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12245 .
addImm(
MI.getOperand(3).getImm())
12246 .
addReg(
MI.getOperand(4).getReg());
12261 .
addReg(
MI.getOperand(1).getReg())
12263 .
addReg(
MI.getOperand(2).getReg())
12266 MI.eraseFromParent();
12271 case ARM::BCCZi64: {
12277 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12282 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12286 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12292 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12296 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12306 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12315 MI.eraseFromParent();
12319 case ARM::Int_eh_sjlj_setjmp:
12320 case ARM::Int_eh_sjlj_setjmp_nofp:
12321 case ARM::tInt_eh_sjlj_setjmp:
12322 case ARM::t2Int_eh_sjlj_setjmp:
12323 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12326 case ARM::Int_eh_sjlj_setup_dispatch:
12327 EmitSjLjDispatchBlock(
MI, BB);
12350 Fn->
insert(BBI, SinkBB);
12352 Register ABSSrcReg =
MI.getOperand(1).getReg();
12353 Register ABSDstReg =
MI.getOperand(0).getReg();
12354 bool ABSSrcKIll =
MI.getOperand(1).isKill();
12355 bool isThumb2 = Subtarget->
isThumb2();
12359 Register NewRsbDstReg =
MRI.createVirtualRegister(
12360 isThumb2 ? &ARM::rGPRRegClass : &ARM::GPRRegClass);
12374 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12381 TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc)).
addMBB(SinkBB)
12388 TII->get(isThumb2 ? ARM::t2RSBri : ARM::RSBri), NewRsbDstReg)
12397 TII->get(ARM::PHI), ABSDstReg)
12402 MI.eraseFromParent();
12407 case ARM::COPY_STRUCT_BYVAL_I32:
12409 return EmitStructByval(
MI, BB);
12410 case ARM::WIN__CHKSTK:
12411 return EmitLowered__chkstk(
MI, BB);
12412 case ARM::WIN__DBZCHK:
12413 return EmitLowered__dbzchk(
MI, BB);
12430 if (!
Node->hasAnyUseOfValue(0)) {
12431 MI.getOperand(0).setIsDead(
true);
12433 if (!
Node->hasAnyUseOfValue(1)) {
12434 MI.getOperand(1).setIsDead(
true);
12438 for (
unsigned I = 0;
I !=
MI.getOperand(4).getImm(); ++
I) {
12439 Register TmpReg =
MRI.createVirtualRegister(isThumb1 ? &ARM::tGPRRegClass
12440 : &ARM::GPRRegClass);
12447 if (
MI.getOpcode() == ARM::MEMCPY) {
12465 MCID = &
TII->get(NewOpc);
12468 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12469 &&
"converted opcode should be the same except for cc_out"
12470 " (and, on Thumb1, pred)");
12480 MI.addOperand(
MI.getOperand(1));
12481 MI.removeOperand(1);
12485 for (
unsigned i =
MI.getNumOperands(); i--;) {
12487 if (
op.isReg() &&
op.isUse()) {
12490 MI.tieOperands(DefIdx, i);
12504 if (!
MI.hasOptionalDef() || !MCID->
operands()[ccOutIdx].isOptionalDef()) {
12505 assert(!NewOpc &&
"Optional cc_out operand required");
12510 bool definesCPSR =
false;
12511 bool deadCPSR =
false;
12512 for (
unsigned i = MCID->
getNumOperands(), e =
MI.getNumOperands(); i != e;
12516 definesCPSR =
true;
12519 MI.removeOperand(i);
12523 if (!definesCPSR) {
12524 assert(!NewOpc &&
"Optional cc_out operand required");
12527 assert(deadCPSR == !Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12529 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12530 "expect uninitialized optional cc_out operand");
12568 switch (
N->getOpcode()) {
12569 default:
return false;
12571 CC =
N->getOperand(0);
12593 EVT VT =
N->getValueType(0);
12594 CC =
N->getOperand(0);
12595 if (
CC.getValueType() != MVT::i1 ||
CC.getOpcode() !=
ISD::SETCC)
12641 EVT VT =
N->getValueType(0);
12644 bool SwapSelectOps;
12646 NonConstantVal, DAG))
12652 OtherOp, NonConstantVal);
12658 CCOp, TrueVal, FalseVal);
12682 if (
N->getOpcode() ==
ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12697 if (!
N->getValueType(0).is64BitVector())
12705 EVT VT =
N->getValueType(0);
12744 EVT VT =
N->getValueType(0);
12750 Opcode = Intrinsic::arm_neon_vpaddls;
12752 Opcode = Intrinsic::arm_neon_vpaddlu;
12780 EVT VT =
N->getValueType(0);
12795 unsigned nextIndex = 0;
12863 return DAG.
getNode(ExtOp, dl, VT, tmp);
12894 if (SRA.getOpcode() !=
ISD::SRA) {
12900 if (
auto Const = dyn_cast<ConstantSDNode>(SRA.getOperand(1))) {
12901 if (Const->getZExtValue() != 31)
12906 if (SRA.getOperand(0) !=
Mul)
12910 SDLoc dl(AddcNode);
12911 unsigned Opcode = 0;
12917 Op0 =
Mul.getOperand(0);
12918 Op1 =
Mul.getOperand(1);
12921 Op0 =
Mul.getOperand(0);
12922 Op1 =
Mul.getOperand(1).getOperand(0);
12925 Op0 =
Mul.getOperand(0).getOperand(0);
12926 Op1 =
Mul.getOperand(1);
12929 Op0 =
Mul->getOperand(0).getOperand(0);
12930 Op1 =
Mul->getOperand(1).getOperand(0);
12939 SDValue HiMLALResult(SMLAL.getNode(), 1);
12940 SDValue LoMLALResult(SMLAL.getNode(), 0);
12946 SDValue resNode(AddcNode, 0);
12975 "Expect an ADDE or SUBE");
12979 "ADDE node has the wrong inputs");
12998 "Expect ADDC with two result values. First: i32");
13018 bool IsLeftOperandMUL =
false;
13023 IsLeftOperandMUL =
true;
13034 SDValue *LowAddSub =
nullptr;
13037 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
13040 if (IsLeftOperandMUL)
13041 HiAddSub = &AddeSubeOp1;
13043 HiAddSub = &AddeSubeOp0;
13048 if (AddcSubcOp0 == MULOp.
getValue(0)) {
13049 LoMul = &AddcSubcOp0;
13050 LowAddSub = &AddcSubcOp1;
13052 if (AddcSubcOp1 == MULOp.
getValue(0)) {
13053 LoMul = &AddcSubcOp1;
13054 LowAddSub = &AddcSubcOp0;
13062 if (AddcSubcNode == HiAddSub->getNode() ||
13078 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
13092 return SDValue(AddeSubeNode, 0);
13103 DAG.
getVTList(MVT::i32, MVT::i32), Ops);
13113 return SDValue(AddeSubeNode, 0);
13125 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13134 SDNode *UmlalNode =
nullptr;
13159 DAG.
getVTList(MVT::i32, MVT::i32), Ops);
13173 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13178 SDNode* AddcNode =
N->getOperand(2).getNode();
13179 SDNode* AddeNode =
N->getOperand(3).getNode();
13187 {N->getOperand(0), N->getOperand(1),
13188 AddcNode->getOperand(0), AddcNode->getOperand(1)});
13212 int32_t imm =
C->getSExtValue();
13213 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
13218 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
13233 int64_t imm =
C->getSExtValue();
13244 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
13245 N->getOperand(0),
RHS,
N->getOperand(2));
13257 if (!Subtarget->hasMVEIntegerOps())
13270 SetCC =
N->getOperand(0);
13273 CC = cast<CondCodeSDNode>(SetCC->
getOperand(2))->get();
13274 TrueVal =
N->getOperand(1);
13275 FalseVal =
N->getOperand(2);
13277 LHS =
N->getOperand(0);
13278 RHS =
N->getOperand(1);
13279 CC = cast<CondCodeSDNode>(
N->getOperand(4))->get();
13280 TrueVal =
N->getOperand(2);
13281 FalseVal =
N->getOperand(3);
13286 unsigned int Opcode = 0;
13315 switch (TrueVal->getOpcode()) {
13334 if (TrueVal !=
LHS || FalseVal !=
RHS)
13337 EVT LeftType =
LHS->getValueType(0);
13338 EVT RightType =
RHS->getValueType(0);
13341 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13345 if (VectorScalarType != MVT::i32)
13353 if (VectorScalarType != MVT::i32)
13366 EVT VT =
N->getValueType(0);
13374 Shft =
N->getOperand(0);
13380 cast<CondCodeSDNode>(Cmp.getOperand(2))->get() !=
ISD::SETLT ||
13381 Cmp.getOperand(0) !=
N->getOperand(1) ||
13382 Cmp.getOperand(1) !=
N->getOperand(2))
13384 Shft =
N->getOperand(1);
13396 ScalarType = MVT::i8;
13399 case (1 << 15) - 1:
13400 ScalarType = MVT::i16;
13403 case (1ULL << 31) - 1:
13404 ScalarType = MVT::i32;
13435 unsigned LegalLanes = 128 / (ShftAmt + 1);
13459 for (
unsigned I = 0;
I < NumParts; ++
I) {
13476 if (!Subtarget->hasMVEIntegerOps())
13491 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13501 if (!Const || !Const->isOne())
13519 EVT VT =
N->getValueType(0);
13521 if (!Subtarget->hasMVEIntegerOps() ||
13550 Opc = Intrinsic::arm_mve_vctp64;
13553 Opc = Intrinsic::arm_mve_vctp32;
13556 Opc = Intrinsic::arm_mve_vctp16;
13559 Opc = Intrinsic::arm_mve_vctp8;
13613 EVT VT =
N->getValueType(0);
13619 switch (
Op.getOpcode()) {
13636 !isa<ConstantSDNode>(N0) && N1->
hasOneUse()) {
13644 unsigned N0RedOp = 0;
13651 unsigned N1RedOp = 0;
13665 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13667 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13674 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13688 LoadSDNode *Load0 = dyn_cast<LoadSDNode>(N0);
13689 LoadSDNode *Load1 = dyn_cast<LoadSDNode>(N1);
13698 if (!BaseLocDecomp0.getBase() ||
13699 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13700 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13702 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13704 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13714 if (IsBefore < 0) {
13717 }
else if (IsBefore > 0) {
13730 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13740 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13750 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13752 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13759 if (!Subtarget->hasMVEIntegerOps())
13765 EVT VT =
N->getValueType(0);
13770 if (VT != MVT::i64)
13781 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13799 std::tie(Ops[0], Ops[1]) = DAG.
SplitScalar(NA, dl, MVT::i32, MVT::i32);
13801 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13850 "Expected shift op");
13852 SDValue ShiftLHS =
N->getOperand(0);
13876 if (
auto *Const = dyn_cast<ConstantSDNode>(N1->
getOperand(1))) {
13877 if (Const->getAPIntValue().ult(256))
13880 Const->getAPIntValue().sgt(-256))
13896 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13897 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13898 "Expected XOR(SHIFT) pattern");
13901 auto *XorC = dyn_cast<ConstantSDNode>(
N->getOperand(1));
13902 auto *ShiftC = dyn_cast<ConstantSDNode>(
N->getOperand(0).getOperand(1));
13903 if (XorC && ShiftC) {
13904 unsigned MaskIdx, MaskLen;
13905 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13906 unsigned ShiftAmt = ShiftC->getZExtValue();
13907 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13908 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13909 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13910 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13920 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13922 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13923 "Expected shift-shift mask");
13936 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT);
13940 if (!Subtarget->hasNEON()) {
13959 return Subtarget->hasFP64();
13962 return Subtarget->hasMVEFloatOps();
13991 if (ST->isThumb() && ST->isThumb1Only())
13995 for (
auto *U :
N->users()) {
13996 switch(U->getOpcode()) {
14009 if (isa<ConstantSDNode>(U->getOperand(0)) ||
14010 isa<ConstantSDNode>(U->getOperand(1)))
14014 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
14015 U->getOperand(1).getOpcode() ==
ISD::SHL)
14025 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
14030 auto *C1ShlC2 = dyn_cast<ConstantSDNode>(
N->getOperand(1));
14031 auto *C2 = dyn_cast<ConstantSDNode>(SHL.getOperand(1));
14032 if (!C1ShlC2 || !C2)
14035 APInt C2Int = C2->getAPIntValue();
14036 APInt C1Int = C1ShlC2->getAPIntValue();
14038 if (C2Int.
uge(C2Width))
14044 if ((C1Int & Mask) != C1Int)
14051 auto LargeImm = [](
const APInt &Imm) {
14052 unsigned Zeros = Imm.countl_zero() + Imm.countr_zero();
14053 return Imm.getBitWidth() - Zeros > 8;
14056 if (LargeImm(C1Int) || LargeImm(C2Int))
14068 SHL.dump();
N->dump());
14103 if (CSINC.getOpcode() !=
ARMISD::CSINC || !CSINC.hasOneUse())
14112 CSINC.getOperand(0)),
14113 CSINC.getOperand(1), CSINC.getOperand(2),
14114 CSINC.getOperand(3));
14133 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
14175 if (!Subtarget->hasVMLxForwarding())
14194 EVT VT =
N->getValueType(0);
14205 EVT VT =
N->getValueType(0);
14206 if (VT != MVT::v2i64)
14215 EVT VT = cast<VTSDNode>(
Op->getOperand(1))->getVT();
14217 return Op->getOperand(0);
14231 And =
And->getOperand(0);
14236 Mask = Mask->getOperand(0);
14239 Mask.getValueType() != MVT::v4i32)
14245 return And->getOperand(0);
14250 if (
SDValue Op0 = IsSignExt(N0)) {
14251 if (
SDValue Op1 = IsSignExt(N1)) {
14257 if (
SDValue Op0 = IsZeroExt(N0)) {
14258 if (
SDValue Op1 = IsZeroExt(N1)) {
14273 EVT VT =
N->getValueType(0);
14274 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14285 if (VT != MVT::i32)
14292 int64_t MulAmt =
C->getSExtValue();
14293 unsigned ShiftAmt = llvm::countr_zero<uint64_t>(MulAmt);
14295 ShiftAmt = ShiftAmt & (32 - 1);
14300 MulAmt >>= ShiftAmt;
14303 if (llvm::has_single_bit<uint32_t>(MulAmt - 1)) {
14311 }
else if (llvm::has_single_bit<uint32_t>(MulAmt + 1)) {
14323 if (llvm::has_single_bit<uint32_t>(MulAmtAbs + 1)) {
14331 }
else if (llvm::has_single_bit<uint32_t>(MulAmtAbs - 1)) {
14361 if (
N->getValueType(0) != MVT::i32)
14370 if (C1 == 255 || C1 == 65535)
14373 SDNode *N0 =
N->getOperand(0).getNode();
14387 if (!C2 || C2 >= 32)
14431 if (Trailing == C2 && C2 + C3 < 32) {
14444 if (Leading == C2 && C2 + C3 < 32) {
14472 EVT VT =
N->getValueType(0);
14476 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14479 APInt SplatBits, SplatUndef;
14480 unsigned SplatBitSize;
14482 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14483 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14484 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14485 SplatBitSize == 64) {
14519 if (!Subtarget->hasV6Ops() ||
14520 (Subtarget->isThumb() &&
14521 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14524 SDValue SRL = OR->getOperand(0);
14525 SDValue SHL = OR->getOperand(1);
14528 SRL = OR->getOperand(1);
14529 SHL = OR->getOperand(0);
14536 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14540 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14541 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14542 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14561 unsigned Opcode = 0;
14562 if (
isS16(OpS16, DAG))
14580 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14583 EVT VT =
N->getValueType(0);
14598 if (VT != MVT::i32)
14611 if (Mask == 0xffff)
14618 if ((Val & ~Mask) != Val)
14643 (Mask == ~Mask2)) {
14646 if (Subtarget->hasDSP() &&
14647 (Mask == 0xffff || Mask == 0xffff0000))
14660 (~Mask == Mask2)) {
14663 if (Subtarget->hasDSP() &&
14664 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14737 EVT VT =
N->getValueType(0);
14742 auto IsFreelyInvertable = [&](
SDValue V) {
14749 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14765 EVT VT =
N->getValueType(0);
14771 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14772 VT == MVT::v8i1 || VT == MVT::v16i1))
14775 APInt SplatBits, SplatUndef;
14776 unsigned SplatBitSize;
14778 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14779 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14780 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14781 SplatBitSize == 64) {
14817 unsigned SplatBitSize;
14820 APInt SplatBits0, SplatBits1;
14824 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14825 HasAnyUndefs) && !HasAnyUndefs) {
14826 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14827 HasAnyUndefs) && !HasAnyUndefs) {
14832 SplatBits0 == ~SplatBits1) {
14862 EVT VT =
N->getValueType(0);
14877 if (Subtarget->hasMVEIntegerOps()) {
14908 ToMask = ~N->getConstantOperandAPInt(2);
14914 isa<ConstantSDNode>(
From->getOperand(1))) {
14915 APInt Shift =
From->getConstantOperandAPInt(1);
14928 unsigned LastActiveBitInA =
A.countr_zero();
14929 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
14930 return LastActiveBitInA - 1 == FirstActiveBitInB;
14935 APInt ToMask, FromMask;
14943 APInt NewToMask, NewFromMask;
14945 if (NewFrom !=
From)
14949 if ((NewToMask & ToMask).getBoolValue())
14974 unsigned InvMask =
N->getConstantOperandVal(2);
14976 unsigned Width = llvm::bit_width<unsigned>(~InvMask) - LSB;
14978 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
14979 "undefined behavior");
14980 unsigned Mask = (1u << Width) - 1;
14982 if ((Mask & (~Mask2)) == 0)
14984 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
14991 APInt ToMask1, FromMask1;
14994 APInt ToMask2, FromMask2;
15000 APInt NewFromMask = FromMask1 | FromMask2;
15001 APInt NewToMask = ToMask1 | ToMask2;
15003 EVT VT =
N->getValueType(0);
15006 if (NewFromMask[0] == 0)
15018 APInt ToMask1 = ~N->getConstantOperandAPInt(2);
15019 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
15021 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
15025 EVT VT =
N->getValueType(0);
15028 N->getOperand(1),
N->getOperand(2));
15042 SDValue CSInc = Cmp->getOperand(0);
15092 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
15093 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15096 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
15098 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15111 SDValue InDouble =
N->getOperand(0);
15120 !cast<LoadSDNode>(InNode)->isVolatile()) {
15126 SDValue BasePtr = LD->getBasePtr();
15128 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
15129 LD->getAlign(), LD->getMemOperand()->getFlags());
15135 LD->getPointerInfo().getWithOffset(4),
15137 LD->getMemOperand()->getFlags());
15149 isa<ConstantSDNode>(InDouble.
getOperand(1))) {
15170 if (!Subtarget->
isLittle() && BVSwap)
15180 if (isa<ConstantSDNode>(BV.
getOperand(2))) {
15188 if (!Subtarget->
isLittle() && BVSwap)
15233 if (Copy.getValueType() == MVT::f32 &&
15235 bool HasGlue = Copy->getNumOperands() == 3;
15236 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
15237 HasGlue ? Copy->getOperand(2) :
SDValue()};
15238 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
15256 if (
LoadSDNode *LN0 = dyn_cast<LoadSDNode>(Op0)) {
15257 if (LN0->hasOneUse() && LN0->isUnindexed() &&
15258 LN0->getMemoryVT() == MVT::i16) {
15261 LN0->getBasePtr(), LN0->getMemOperand());
15279 EVT VT =
N->getValueType(0);
15313 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15314 for (
unsigned i = 0; i < NumElts; ++i) {
15315 SDNode *Elt =
N->getOperand(i).getNode();
15332 if (
N->getNumOperands() == 2)
15338 EVT VT =
N->getValueType(0);
15344 for (
unsigned i = 0; i < NumElts; ++i) {
15370 EVT VT =
N->getValueType(0);
15378 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15383 Use->getValueType(0).isFloatingPoint())
15391 unsigned NumOfBitCastedElts = 0;
15393 unsigned NumOfRelevantElts = NumElts;
15394 for (
unsigned Idx = 0;
Idx < NumElts; ++
Idx) {
15399 ++NumOfBitCastedElts;
15400 }
else if (Elt.
isUndef() || isa<ConstantSDNode>(Elt))
15403 --NumOfRelevantElts;
15407 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15425 for (
unsigned Idx = 0 ;
Idx < NumElts; ++
Idx) {
15430 V->getOperand(0).getValueType() == MVT::i32)
15432 V = V.getOperand(0);
15449 EVT VT =
N->getValueType(0);
15456 if (
Op->getOperand(0).getValueType() == VT)
15457 return Op->getOperand(0);
15472 if (
Op.getValueType() == MVT::i32) {
15483 EVT VT =
N->getValueType(0);
15488 if (ST->isLittle())
15492 if (
Op.getValueType() == VT)
15501 if (
Op->getOperand(0).getValueType() == VT)
15502 return Op->getOperand(0);
15511 if (!Subtarget->hasMVEIntegerOps())
15514 EVT VT =
N->getValueType(0);
15545 EVT VT =
N->getValueType(0);
15546 SDNode *Elt =
N->getOperand(1).getNode();
15561 Vec, V,
N->getOperand(2));
15571 EVT VT =
N->getValueType(0);
15580 Ext.getOperand(0).getValueType() == MVT::f32)
15581 Ext = Ext.getOperand(0);
15583 !isa<ConstantSDNode>(Ext.getOperand(1)) ||
15584 Ext.getConstantOperandVal(1) % 2 != 0)
15586 if (Ext->hasOneUse() && (Ext->user_begin()->getOpcode() ==
ISD::SINT_TO_FP ||
15590 SDValue Op0 = Ext.getOperand(0);
15593 unsigned Lane = Ext.getConstantOperandVal(1);
15599 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15600 isa<ConstantSDNode>(V->getOperand(1)) &&
15601 V->getConstantOperandVal(1) == Lane + 1 &&
15602 V->getOperand(0).getResNo() == ResNo;
15604 if (OtherIt == Op0->
users().end())
15609 SDValue OtherExt(*OtherIt, 0);
15622 DCI.
DAG.
getConstant(Ext.getConstantOperandVal(1) / 2, dl, MVT::i32));
15634 EVT VT =
N->getValueType(0);
15640 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15642 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15644 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15647 while (
X.getValueType() != VT &&
X->getOpcode() ==
ISD::BITCAST)
15648 X =
X->getOperand(0);
15649 if (
X.getValueType() == VT)
15655 isa<ConstantSDNode>(
N->getOperand(1)) &&
15657 return Op0.
getOperand(
N->getConstantOperandVal(1));
15662 isa<ConstantSDNode>(
N->getOperand(1)) &&
15667 unsigned Offset =
N->getConstantOperandVal(1);
15679 unsigned Idx =
N->getConstantOperandVal(1);
15693 EVT VT =
N->getValueType(0);
15697 cast<VTSDNode>(
N->getOperand(1))->getVT() ==
15698 Op.getOperand(0).getValueType().getScalarType())
15708 SDValue SubVec =
N->getOperand(1);
15709 uint64_t IdxVal =
N->getConstantOperandVal(2);
15720 if (IdxVal == 0 && Vec.
isUndef())
15726 (IdxVal != 0 && IdxVal != NumSubElts))
15799 EVT VT =
N->getValueType(0);
15810 unsigned HalfElts = NumElts/2;
15812 for (
unsigned n = 0; n < NumElts; ++n) {
15815 if (MaskElt < (
int)HalfElts)
15817 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
15818 NewElt = HalfElts + MaskElt - NumElts;
15845 bool SimpleConstIncOnly,
15853 bool isLoadOp =
true;
15854 bool isLaneOp =
false;
15857 bool hasAlignment =
true;
15858 unsigned NewOpc = 0;
15859 unsigned NumVecs = 0;
15860 if (
Target.isIntrinsic) {
15861 unsigned IntNo =
N->getConstantOperandVal(1);
15865 case Intrinsic::arm_neon_vld1:
15869 case Intrinsic::arm_neon_vld2:
15873 case Intrinsic::arm_neon_vld3:
15877 case Intrinsic::arm_neon_vld4:
15881 case Intrinsic::arm_neon_vld1x2:
15884 hasAlignment =
false;
15886 case Intrinsic::arm_neon_vld1x3:
15889 hasAlignment =
false;
15891 case Intrinsic::arm_neon_vld1x4:
15894 hasAlignment =
false;
15896 case Intrinsic::arm_neon_vld2dup:
15900 case Intrinsic::arm_neon_vld3dup:
15904 case Intrinsic::arm_neon_vld4dup:
15908 case Intrinsic::arm_neon_vld2lane:
15913 case Intrinsic::arm_neon_vld3lane:
15918 case Intrinsic::arm_neon_vld4lane:
15923 case Intrinsic::arm_neon_vst1:
15928 case Intrinsic::arm_neon_vst2:
15933 case Intrinsic::arm_neon_vst3:
15938 case Intrinsic::arm_neon_vst4:
15943 case Intrinsic::arm_neon_vst2lane:
15949 case Intrinsic::arm_neon_vst3lane:
15955 case Intrinsic::arm_neon_vst4lane:
15961 case Intrinsic::arm_neon_vst1x2:
15965 hasAlignment =
false;
15967 case Intrinsic::arm_neon_vst1x3:
15971 hasAlignment =
false;
15973 case Intrinsic::arm_neon_vst1x4:
15977 hasAlignment =
false;
15982 switch (
N->getOpcode()) {
16018 VecTy =
N->getValueType(0);
16019 }
else if (
Target.isIntrinsic) {
16020 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
16023 "Node has to be a load, a store, or an intrinsic!");
16024 VecTy =
N->getOperand(1).getValueType();
16032 if (isLaneOp || isVLDDUPOp)
16035 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
16041 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
16047 EVT AlignedVecTy = VecTy;
16064 if (isa<LSBaseSDNode>(
N)) {
16067 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
16068 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
16079 Alignment =
Align(1);
16085 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16087 for (n = 0; n < NumResultVecs; ++n)
16088 Tys[n] = AlignedVecTy;
16089 Tys[n++] = MVT::i32;
16090 Tys[n] = MVT::Other;
16105 unsigned LastOperand =
16106 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
16107 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
16116 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::STORE) {
16127 for (
unsigned i = 0; i < NumResultVecs; ++i)
16132 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::LOAD) {
16133 SDValue &LdVal = NewResults[0];
16169 switch (
N->getOpcode()) {
16172 if (isa<ConstantSDNode>(
N->getOperand(1))) {
16173 *
Ptr =
N->getOperand(0);
16174 *CInc =
N->getOperand(1);
16180 if (isa<ConstantSDNode>(
N->getOperand(2))) {
16181 *
Ptr =
N->getOperand(1);
16182 *CInc =
N->getOperand(2);
16231 unsigned ConstInc =
16253 unsigned UserOffset =
16256 if (!UserOffset || UserOffset <=
Offset)
16259 unsigned NewConstInc = UserOffset -
Offset;
16269 unsigned NumValidUpd = BaseUpdates.
size();
16270 for (
unsigned I = 0;
I < NumValidUpd;) {
16274 std::swap(BaseUpdates[
I], BaseUpdates[NumValidUpd]);
16282 BaseUpdates.
resize(NumValidUpd);
16287 std::stable_sort(BaseUpdates.
begin(), BaseUpdates.
end(),
16289 return LHS.ConstInc < RHS.ConstInc;
16318 unsigned IntNo =
N->getConstantOperandVal(1);
16319 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16321 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16343 bool isLoadOp =
true;
16344 unsigned NewOpc = 0;
16345 unsigned NumVecs = 0;
16349 case Intrinsic::arm_mve_vld2q:
16353 case Intrinsic::arm_mve_vld4q:
16357 case Intrinsic::arm_mve_vst2q:
16362 case Intrinsic::arm_mve_vst4q:
16372 VecTy =
N->getValueType(0);
16374 VecTy =
N->getOperand(3).getValueType();
16388 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16390 for (n = 0; n < NumResultVecs; ++n)
16392 Tys[n++] = MVT::i32;
16393 Tys[n] = MVT::Other;
16402 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16410 for (
unsigned i = 0; i < NumResultVecs; ++i)
16429 EVT VT =
N->getValueType(0);
16435 SDNode *VLD =
N->getOperand(0).getNode();
16438 unsigned NumVecs = 0;
16439 unsigned NewOpc = 0;
16441 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16444 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16447 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16459 if (
Use.getResNo() == NumVecs)
16463 VLDLaneNo !=
User->getConstantOperandVal(1))
16470 for (n = 0; n < NumVecs; ++n)
16472 Tys[n] = MVT::Other;
16482 unsigned ResNo =
Use.getResNo();
16484 if (ResNo == NumVecs)
16491 std::vector<SDValue> VLDDupResults;
16492 for (
unsigned n = 0; n < NumVecs; ++n)
16506 EVT VT =
N->getValueType(0);
16509 if (Subtarget->hasMVEIntegerOps()) {
16513 ExtractVT = MVT::i32;
16515 N->getOperand(0),
N->getOperand(1));
16527 Op =
Op.getOperand(0);
16532 unsigned EltSize =
Op.getScalarValueSizeInBits();
16534 unsigned Imm =
Op.getConstantOperandVal(0);
16550 if (Subtarget->hasMVEIntegerOps()) {
16553 if (
Op.getValueType() == MVT::f32)
16556 else if (
Op.getValueType() == MVT::f16)
16561 if (!Subtarget->hasNEON())
16568 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16569 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16570 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16575 LD->getMemoryVT(), LD->getMemOperand());
16586 EVT VT =
N->getValueType(0);
16608 assert(StVT != VT &&
"Cannot truncate to the same type");
16618 if (0 != (NumElems * FromEltSz) % ToEltSz)
16621 unsigned SizeRatio = FromEltSz / ToEltSz;
16626 NumElems * SizeRatio);
16632 for (
unsigned i = 0; i < NumElems; ++i)
16646 MVT StoreType = MVT::i8;
16648 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16667 unsigned E = (ToEltSz * NumElems) / StoreType.
getSizeInBits();
16668 for (
unsigned I = 0;
I < E;
I++) {
16699 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16702 unsigned NumElements = 4;
16719 unsigned Off0 = Rev ? NumElts : 0;
16720 unsigned Off1 = Rev ? 0 : NumElts;
16722 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16723 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16725 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16732 if (
auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(Trunc.
getOperand(0)))
16733 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16753 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16768 NewToVT, Alignment, MMOFlags, AAInfo);
16801 unsigned NewOffset =
16809 NewToVT, Alignment, MMOFlags, AAInfo);
16831 {Extract.getOperand(0), Extract.getOperand(1)});
16862 if (Subtarget->hasNEON())
16866 if (Subtarget->hasMVEFloatOps())
16870 if (Subtarget->hasMVEIntegerOps()) {
16946 if (!Subtarget->hasNEON())
16950 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
16955 if (!isa<BuildVectorSDNode>(ConstVec))
16958 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
16960 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
16962 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
16963 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
16974 if (
C == -1 ||
C == 0 ||
C > 32)
16979 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
16980 Intrinsic::arm_neon_vcvtfp2fxu;
16983 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
16986 if (IntBits < FloatBits)
16994 if (!Subtarget->hasMVEFloatOps())
17002 EVT VT =
N->getValueType(0);
17007 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
17011 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
17012 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
17014 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
17027 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
17038 EVT VT =
N->getValueType(0);
17041 if (!
N->getFlags().hasAllowReassociation())
17048 unsigned Opc =
A.getConstantOperandVal(0);
17049 if (Opc != Intrinsic::arm_mve_vcmlaq)
17054 A.getOperand(3),
A.getOperand(4));
17086 if (!Subtarget->hasNEON())
17090 unsigned OpOpcode =
Op.getNode()->getOpcode();
17091 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
17095 SDValue ConstVec =
N->getOperand(1);
17096 if (!isa<BuildVectorSDNode>(ConstVec))
17099 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
17101 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
17103 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17104 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17124 int32_t
C = IntVal.exactLogBase2();
17125 if (
C == -1 ||
C == 0 ||
C > 32)
17131 if (IntBits < FloatBits)
17133 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
17135 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
17136 : Intrinsic::arm_neon_vcvtfxu2fp;
17144 if (!ST->hasMVEIntegerOps())
17148 EVT ResVT =
N->getValueType(0);
17176 EVT AVT =
A.getValueType();
17182 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
17183 EVT AVT =
A.getValueType();
17195 if (ExtTypeMatches(
A, ExtTypes))
17196 return ExtendIfNeeded(
A, ExtendCode);
17199 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
17206 if (Ext->getOpcode() != ExtendCode)
17209 if (ExtTypeMatches(
A, ExtTypes))
17210 return ExtendIfNeeded(
A, ExtendCode);
17223 if (ResVT !=
RetTy)
17226 if (
Mul->getOpcode() == ExtendCode &&
17227 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17229 Mul =
Mul->getOperand(0);
17238 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17239 A = ExtendIfNeeded(
A, ExtendCode);
17240 B = ExtendIfNeeded(
B, ExtendCode);
17258 if (
Mul->getOpcode() == ExtendCode &&
17259 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17261 Mul =
Mul->getOperand(0);
17270 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17271 A = ExtendIfNeeded(
A, ExtendCode);
17272 B = ExtendIfNeeded(
B, ExtendCode);
17283 EVT VT = Ops[0].getValueType();
17284 if (VT == MVT::v16i8) {
17286 "Unexpected illegal long reduction opcode");
17291 DAG.
getVTList(MVT::v8i16, MVT::v8i16), Ops[0]);
17294 DAG.
getVTList(MVT::v8i16, MVT::v8i16), Ops[1]);
17315 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17318 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17382 Op =
Op->getOperand(1);
17384 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17386 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17403 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17404 auto *Shuf = dyn_cast<ShuffleVectorSDNode>(
N->getOperand(VecOp));
17405 if (!Shuf || !Shuf->getOperand(1).isUndef())
17410 APInt SetElts(Mask.size(), 0);
17411 for (
int E : Mask) {
17412 if (E < 0 || E >= (
int)Mask.size())
17419 if (
N->getNumOperands() != VecOp + 1) {
17420 auto *Shuf2 = dyn_cast<ShuffleVectorSDNode>(
N->getOperand(VecOp + 1));
17421 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17427 if (
Op.getValueType().isVector())
17439 unsigned IsTop =
N->getConstantOperandVal(2);
17446 if (Op0->
isUndef() && !IsTop)
17460 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17462 APInt Op0DemandedElts =
17463 IsTop ? Op1DemandedElts
17478 unsigned IsTop =
N->getConstantOperandVal(2);
17480 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17481 APInt Op0DemandedElts =
17493 EVT VT =
N->getValueType(0);
17497 auto *Shuf0 = dyn_cast<ShuffleVectorSDNode>(
LHS);
17498 auto *Shuf1 = dyn_cast<ShuffleVectorSDNode>(
RHS);
17500 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17501 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17505 LHS.getOperand(0),
RHS.getOperand(0));
17519 if (
auto C = dyn_cast<ConstantSDNode>(
N->getOperand(2))) {
17520 int ShiftAmt =
C->getSExtValue();
17521 if (ShiftAmt == 0) {
17527 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17528 unsigned NewOpcode =
17544 unsigned IntNo =
N->getConstantOperandVal(0);
17555 case Intrinsic::arm_neon_vshifts:
17556 case Intrinsic::arm_neon_vshiftu:
17557 case Intrinsic::arm_neon_vrshifts:
17558 case Intrinsic::arm_neon_vrshiftu:
17559 case Intrinsic::arm_neon_vrshiftn:
17560 case Intrinsic::arm_neon_vqshifts:
17561 case Intrinsic::arm_neon_vqshiftu:
17562 case Intrinsic::arm_neon_vqshiftsu:
17563 case Intrinsic::arm_neon_vqshiftns:
17564 case Intrinsic::arm_neon_vqshiftnu:
17565 case Intrinsic::arm_neon_vqshiftnsu:
17566 case Intrinsic::arm_neon_vqrshiftns:
17567 case Intrinsic::arm_neon_vqrshiftnu:
17568 case Intrinsic::arm_neon_vqrshiftnsu: {
17569 EVT VT =
N->getOperand(1).getValueType();
17571 unsigned VShiftOpc = 0;
17574 case Intrinsic::arm_neon_vshifts:
17575 case Intrinsic::arm_neon_vshiftu:
17580 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17587 case Intrinsic::arm_neon_vrshifts:
17588 case Intrinsic::arm_neon_vrshiftu:
17593 case Intrinsic::arm_neon_vqshifts:
17594 case Intrinsic::arm_neon_vqshiftu:
17599 case Intrinsic::arm_neon_vqshiftsu:
17604 case Intrinsic::arm_neon_vrshiftn:
17605 case Intrinsic::arm_neon_vqshiftns:
17606 case Intrinsic::arm_neon_vqshiftnu:
17607 case Intrinsic::arm_neon_vqshiftnsu:
17608 case Intrinsic::arm_neon_vqrshiftns:
17609 case Intrinsic::arm_neon_vqrshiftnu:
17610 case Intrinsic::arm_neon_vqrshiftnsu:
17622 case Intrinsic::arm_neon_vshifts:
17623 case Intrinsic::arm_neon_vshiftu:
17626 case Intrinsic::arm_neon_vrshifts:
17629 case Intrinsic::arm_neon_vrshiftu:
17632 case Intrinsic::arm_neon_vrshiftn:
17635 case Intrinsic::arm_neon_vqshifts:
17638 case Intrinsic::arm_neon_vqshiftu:
17641 case Intrinsic::arm_neon_vqshiftsu:
17644 case Intrinsic::arm_neon_vqshiftns:
17647 case Intrinsic::arm_neon_vqshiftnu:
17650 case Intrinsic::arm_neon_vqshiftnsu:
17653 case Intrinsic::arm_neon_vqrshiftns:
17656 case Intrinsic::arm_neon_vqrshiftnu:
17659 case Intrinsic::arm_neon_vqrshiftnsu:
17665 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17666 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
17669 case Intrinsic::arm_neon_vshiftins: {
17670 EVT VT =
N->getOperand(1).getValueType();
17672 unsigned VShiftOpc = 0;
17676 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
17683 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17684 N->getOperand(1),
N->getOperand(2),
17688 case Intrinsic::arm_neon_vqrshifts:
17689 case Intrinsic::arm_neon_vqrshiftu:
17693 case Intrinsic::arm_neon_vbsl: {
17696 N->getOperand(2),
N->getOperand(3));
17698 case Intrinsic::arm_mve_vqdmlah:
17699 case Intrinsic::arm_mve_vqdmlash:
17700 case Intrinsic::arm_mve_vqrdmlah:
17701 case Intrinsic::arm_mve_vqrdmlash:
17702 case Intrinsic::arm_mve_vmla_n_predicated:
17703 case Intrinsic::arm_mve_vmlas_n_predicated:
17704 case Intrinsic::arm_mve_vqdmlah_predicated:
17705 case Intrinsic::arm_mve_vqdmlash_predicated:
17706 case Intrinsic::arm_mve_vqrdmlah_predicated:
17707 case Intrinsic::arm_mve_vqrdmlash_predicated: {
17712 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
17719 case Intrinsic::arm_mve_minv:
17720 case Intrinsic::arm_mve_maxv:
17721 case Intrinsic::arm_mve_minav:
17722 case Intrinsic::arm_mve_maxav:
17723 case Intrinsic::arm_mve_minv_predicated:
17724 case Intrinsic::arm_mve_maxv_predicated:
17725 case Intrinsic::arm_mve_minav_predicated:
17726 case Intrinsic::arm_mve_maxav_predicated: {
17729 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
17736 case Intrinsic::arm_mve_addv: {
17739 bool Unsigned =
N->getConstantOperandVal(2);
17744 case Intrinsic::arm_mve_addlv:
17745 case Intrinsic::arm_mve_addlv_predicated: {
17748 bool Unsigned =
N->getConstantOperandVal(2);
17749 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
17754 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
17777 EVT VT =
N->getValueType(0);
17779 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
17780 N->getOperand(0)->getOpcode() ==
ISD::AND &&
17781 N->getOperand(0)->hasOneUse()) {
17789 ConstantSDNode *ShiftAmtNode = dyn_cast<ConstantSDNode>(
N->getOperand(1));
17798 if (AndMask == 255 || AndMask == 65535)
17802 if (MaskedBits > ShiftAmt) {
17817 if (ST->hasMVEIntegerOps())
17822 switch (
N->getOpcode()) {
17835 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
17836 unsigned VShiftOpc =
17839 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
17855 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
17858 EVT FromVT = LD->getValueType(0);
17859 EVT ToVT =
N->getValueType(0);
17866 unsigned NumElements = 0;
17867 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
17869 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
17871 if (NumElements == 0 ||
17881 SDValue BasePtr = LD->getBasePtr();
17882 Align Alignment = LD->getOriginalAlign();
17903 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
17904 Alignment, MMOFlags, AAInfo);
17910 if (FromEltVT == MVT::f16) {
17913 for (
unsigned i = 0; i < Loads.
size(); i++) {
17939 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
17943 EVT VT =
N->getValueType(0);
17947 if (VT == MVT::i32 &&
17948 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
17950 isa<ConstantSDNode>(Lane)) {
17953 switch (
N->getOpcode()) {
17967 if (ST->hasMVEIntegerOps())
17976 if (ST->hasMVEFloatOps())
17987 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
17991 EVT VT =
Op.getValueType();
17994 if (VT != MVT::i32 ||
17996 !isa<ConstantSDNode>(
Op.getOperand(1)) ||
18007 APInt MaxC = Max.getConstantOperandAPInt(1);
18010 !(MinC + 1).isPowerOf2())
18028 EVT VT =
N->getValueType(0);
18031 if (VT == MVT::i32)
18034 if (!ST->hasMVEIntegerOps())
18040 if (VT != MVT::v4i32 && VT != MVT::v8i16)
18043 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
18051 if (VT == MVT::v4i32)
18052 SaturateC =
APInt(32, (1 << 15) - 1,
true);
18054 SaturateC =
APInt(16, (1 << 7) - 1,
true);
18061 MaxC != ~SaturateC)
18066 if (IsSignedSaturate(
N, N0.
getNode())) {
18069 if (VT == MVT::v4i32) {
18070 HalfVT = MVT::v8i16;
18071 ExtVT = MVT::v4i16;
18073 HalfVT = MVT::v16i8;
18088 auto IsUnsignedSaturate = [&](
SDNode *Min) {
18094 if (VT == MVT::v4i32)
18095 SaturateC =
APInt(32, (1 << 16) - 1,
true);
18097 SaturateC =
APInt(16, (1 << 8) - 1,
true);
18106 if (IsUnsignedSaturate(
N)) {
18110 if (VT == MVT::v4i32) {
18111 HalfVT = MVT::v8i16;
18112 ExtConst = 0x0000FFFF;
18114 HalfVT = MVT::v16i8;
18136 const APInt *CV = &
C->getAPIntValue();
18154 SDValue Op0 = CMOV->getOperand(0);
18155 SDValue Op1 = CMOV->getOperand(1);
18156 auto CC = CMOV->getConstantOperandAPInt(2).getLimitedValue();
18157 SDValue CmpZ = CMOV->getOperand(3);
18193 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
18200 if ((OrCI & Known.
Zero) != OrCI)
18206 EVT VT =
X.getValueType();
18207 unsigned BitInX = AndC->
logBase2();
18215 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
18216 BitInY < NumActiveBits; ++BitInY) {
18217 if (OrCI[BitInY] == 0)
18220 Mask.setBit(BitInY);
18237 switch (
N->getOpcode()) {
18241 if (!isa<ConstantSDNode>(
N.getOperand(1)))
18243 if (!cast<ConstantSDNode>(
N.getOperand(1))->isOne())
18249 auto *Const = dyn_cast<ConstantSDNode>(
N.getOperand(1));
18252 if (Const->isZero())
18254 else if (Const->isOne())
18258 CC = cast<CondCodeSDNode>(
N.getOperand(2))->get();
18262 unsigned IntOp =
N.getConstantOperandVal(1);
18263 if (IntOp != Intrinsic::test_start_loop_iterations &&
18264 IntOp != Intrinsic::loop_decrement_reg)
18290 bool Negate =
false;
18296 Cond =
N->getOperand(1);
18297 Dest =
N->getOperand(2);
18300 CC = cast<CondCodeSDNode>(
N->getOperand(1))->get();
18301 Cond =
N->getOperand(2);
18302 Dest =
N->getOperand(4);
18303 if (
auto *Const = dyn_cast<ConstantSDNode>(
N->getOperand(3))) {
18304 if (!Const->isOne() && !Const->isZero())
18306 Imm = Const->getZExtValue();
18334 assert((IsTrueIfZero(
CC, Imm) || IsFalseIfZero(
CC, Imm)) &&
18335 "unsupported condition");
18340 unsigned IntOp =
Int->getConstantOperandVal(1);
18341 assert((
N->hasOneUse() &&
N->user_begin()->getOpcode() ==
ISD::BR) &&
18342 "expected single br user");
18343 SDNode *Br = *
N->user_begin();
18353 if (IntOp == Intrinsic::test_start_loop_iterations) {
18357 if (IsTrueIfZero(
CC, Imm)) {
18358 SDValue Ops[] = {Chain, Setup, Dest};
18363 UpdateUncondBr(Br, Dest, DAG);
18365 SDValue Ops[] = {Chain, Setup, OtherTarget};
18378 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18386 if (
Target == OtherTarget)
18387 UpdateUncondBr(Br, Dest, DAG);
18423 LHS->getOperand(0)->getOperand(2),
18424 LHS->getOperand(0)->getOperand(3));
18438 EVT VT =
N->getValueType(0);
18442 SDValue FalseVal =
N->getOperand(0);
18443 SDValue TrueVal =
N->getOperand(1);
18448 if (!Subtarget->
isThumb1Only() && Subtarget->hasV6T2Ops()) {
18486 LHS->getOperand(2),
LHS->getOperand(3));
18496 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18500 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18502 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18511 if (!Subtarget->
isThumb1Only() && Subtarget->hasV5TOps()) {
18576 const APInt *TrueConst;
18578 ((FalseVal.getOpcode() ==
ARMISD::SUBC && FalseVal.getOperand(0) ==
LHS &&
18579 FalseVal.getOperand(1) ==
RHS) ||
18583 unsigned ShiftAmount = TrueConst->
logBase2();
18598 if (Known.
Zero == 0xfffffffe)
18601 else if (Known.
Zero == 0xffffff00)
18604 else if (Known.
Zero == 0xffff0000)
18617 EVT DstVT =
N->getValueType(0);
18620 if (ST->hasMVEIntegerOps() && Src.getOpcode() ==
ARMISD::VDUP) {
18621 EVT SrcVT = Src.getValueType();
18629 Src.getOperand(0).getValueType().getScalarSizeInBits() <=
18630 Src.getValueType().getScalarSizeInBits())
18631 Src = Src.getOperand(0);
18635 EVT SrcVT = Src.getValueType();
18655 EVT VT =
N->getValueType(0);
18663 if (
N->getNumOperands() == 2 &&
18667 N->getOperand(0).getOperand(1),
18668 N->getOperand(1).getOperand(0),
18669 N->getOperand(1).getOperand(1));
18672 if (
N->getNumOperands() == 2 &&
18675 auto *S0 = cast<ShuffleVectorSDNode>(
N->getOperand(0).getNode());
18676 auto *
S1 = cast<ShuffleVectorSDNode>(
N->getOperand(1).getNode());
18678 if (S0->getOperand(0) ==
S1->getOperand(0) &&
18679 S0->getOperand(1) ==
S1->getOperand(1)) {
18682 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
18702 return Op.getOpcode() == ISD::BUILD_VECTOR ||
18703 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
18704 (Op.getOpcode() == ISD::BITCAST &&
18705 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
18708 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
18710 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
18727 int SPFI = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
18728 int NumIns =
N->getNumOperands();
18729 assert((NumIns == 2 || NumIns == 4) &&
18730 "Expected 2 or 4 inputs to an MVETrunc");
18732 if (
N->getNumOperands() == 4)
18736 for (
int I = 0;
I < NumIns;
I++) {
18738 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18758 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
18761 EVT FromVT = LD->getMemoryVT();
18762 EVT ToVT =
N->getValueType(0);
18769 unsigned NumElements = 0;
18770 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
18772 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
18774 assert(NumElements != 0);
18780 LD->getExtensionType() != NewExtType)
18787 SDValue BasePtr = LD->getBasePtr();
18788 Align Alignment = LD->getOriginalAlign();
18807 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18808 Alignment, MMOFlags, AAInfo);
18824 EVT VT =
N->getValueType(0);
18826 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
18827 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
18829 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18831 auto Extend = [&](
SDValue V) {
18841 SDValue Ext = Extend(
N->getOperand(0));
18846 if (
auto *SVN = dyn_cast<ShuffleVectorSDNode>(
N->getOperand(0))) {
18849 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
18854 auto CheckInregMask = [&](
int Start,
int Offset) {
18862 if (CheckInregMask(0, 0))
18864 else if (CheckInregMask(0, 1))
18865 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18866 else if (CheckInregMask(0, Mask.size()))
18868 else if (CheckInregMask(0, Mask.size() + 1))
18869 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18874 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18878 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18885 if (
N->getOperand(0)->getOpcode() ==
ISD::LOAD)
18895 int SPFI = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
18896 int NumOuts =
N->getNumValues();
18897 assert((NumOuts == 2 || NumOuts == 4) &&
18898 "Expected 2 or 4 outputs to an MVEEXT");
18899 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18901 if (
N->getNumOperands() == 4)
18907 StackPtr, MPI,
Align(4));
18910 for (
int I = 0;
I < NumOuts;
I++) {
18912 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18913 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
18918 VT, Chain,
Ptr, MPI, LoadVT,
Align(4));
18927 switch (
N->getOpcode()) {
19044 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19051 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19062 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19070 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
19072 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
19080 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
19082 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
19090 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19101 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19109 if (
N->getOperand(1) ==
N->getOperand(2))
19110 return N->getOperand(1);
19114 switch (
N->getConstantOperandVal(1)) {
19115 case Intrinsic::arm_neon_vld1:
19116 case Intrinsic::arm_neon_vld1x2:
19117 case Intrinsic::arm_neon_vld1x3:
19118 case Intrinsic::arm_neon_vld1x4:
19119 case Intrinsic::arm_neon_vld2:
19120 case Intrinsic::arm_neon_vld3:
19121 case Intrinsic::arm_neon_vld4:
19122 case Intrinsic::arm_neon_vld2lane:
19123 case Intrinsic::arm_neon_vld3lane:
19124 case Intrinsic::arm_neon_vld4lane:
19125 case Intrinsic::arm_neon_vld2dup:
19126 case Intrinsic::arm_neon_vld3dup:
19127 case Intrinsic::arm_neon_vld4dup:
19128 case Intrinsic::arm_neon_vst1:
19129 case Intrinsic::arm_neon_vst1x2:
19130 case Intrinsic::arm_neon_vst1x3:
19131 case Intrinsic::arm_neon_vst1x4:
19132 case Intrinsic::arm_neon_vst2:
19133 case Intrinsic::arm_neon_vst3:
19134 case Intrinsic::arm_neon_vst4:
19135 case Intrinsic::arm_neon_vst2lane:
19136 case Intrinsic::arm_neon_vst3lane:
19137 case Intrinsic::arm_neon_vst4lane:
19139 case Intrinsic::arm_mve_vld2q:
19140 case Intrinsic::arm_mve_vld4q:
19141 case Intrinsic::arm_mve_vst2q:
19142 case Intrinsic::arm_mve_vst4q:
19159 unsigned *
Fast)
const {
19168 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
19170 if (AllowsUnaligned) {
19172 *
Fast = Subtarget->hasV7Ops();
19177 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
19181 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->
isLittle())) {
19188 if (!Subtarget->hasMVEIntegerOps())
19192 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
19193 Ty == MVT::v2i1)) {
19201 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
19217 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
19218 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
19219 Ty == MVT::v2f64) {
19232 if ((
Op.isMemcpy() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
19233 !FuncAttributes.
hasFnAttr(Attribute::NoImplicitFloat)) {
19235 if (
Op.size() >= 16 &&
19241 }
else if (
Op.size() >= 8 &&
19262 return (SrcBits == 64 && DestBits == 32);
19271 return (SrcBits == 64 && DestBits == 32);
19307 return Subtarget->hasFullFP16();
19314 if (!Subtarget->hasMVEIntegerOps())
19332 if (
auto *Ld = dyn_cast<MaskedLoadSDNode>(ExtVal.
getOperand(0))) {
19333 if (Ld->isExpandingLoad())
19337 if (Subtarget->hasMVEIntegerOps())
19382bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19384 if (Subtarget->useSoftFloat())
19393 return Subtarget->hasMVEFloatOps();
19411 unsigned Scale = 1;
19428 if ((V & (Scale - 1)) != 0)
19430 return isUInt<5>(V / Scale);
19437 if (VT.
isVector() && Subtarget->hasNEON())
19440 !Subtarget->hasMVEFloatOps())
19443 bool IsNeg =
false;
19449 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19452 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19456 return isShiftedUInt<7,2>(V);
19459 return isShiftedUInt<7,1>(V);
19461 return isUInt<7>(V);
19468 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19469 return isShiftedUInt<8, 1>(V);
19472 return isShiftedUInt<8, 2>(V);
19474 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19477 return isUInt<8>(V);
19478 return isUInt<12>(V);
19504 default:
return false;
19509 return isUInt<12>(V);
19512 return isUInt<8>(V);
19517 return isShiftedUInt<8, 2>(V);
19523 int Scale = AM.
Scale;
19528 default:
return false;
19536 Scale = Scale & ~1;
19537 return Scale == 2 || Scale == 4 || Scale == 8;
19554 if (Scale & 1)
return false;
19561 const int Scale = AM.
Scale;
19571 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
19587 switch (AM.
Scale) {
19604 int Scale = AM.
Scale;
19606 default:
return false;
19610 if (Scale < 0) Scale = -Scale;
19618 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
19631 if (Scale & 1)
return false;
19644 if (!Subtarget->isThumb())
19651 return Imm >= 0 && Imm <= 255;
19660 int64_t AbsImm = std::abs(Imm);
19661 if (!Subtarget->isThumb())
19666 return AbsImm >= 0 && AbsImm <= 255;
19701 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
19705 int RHSC = (int)
RHS->getZExtValue();
19706 if (RHSC < 0 && RHSC > -256) {
19716 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
19719 int RHSC = (int)
RHS->getZExtValue();
19720 if (RHSC < 0 && RHSC > -0x1000) {
19762 int RHSC = (int)
RHS->getZExtValue();
19763 if (RHSC < 0 && RHSC > -0x100) {
19768 }
else if (RHSC > 0 && RHSC < 0x100) {
19779 bool isSEXTLoad,
bool IsMasked,
bool isLE,
19784 if (!isa<ConstantSDNode>(
Ptr->getOperand(1)))
19790 bool CanChangeType = isLE && !IsMasked;
19793 int RHSC = (int)
RHS->getZExtValue();
19795 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
19796 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
19801 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
19812 if (VT == MVT::v4i16) {
19813 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
19815 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
19816 if (IsInRange(RHSC, 0x80, 1))
19818 }
else if (Alignment >= 4 &&
19819 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
19820 IsInRange(RHSC, 0x80, 4))
19822 else if (Alignment >= 2 &&
19823 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
19824 IsInRange(RHSC, 0x80, 2))
19826 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
19845 bool isSEXTLoad =
false;
19846 bool IsMasked =
false;
19848 Ptr = LD->getBasePtr();
19849 VT = LD->getMemoryVT();
19850 Alignment = LD->getAlign();
19852 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
19853 Ptr = ST->getBasePtr();
19854 VT = ST->getMemoryVT();
19855 Alignment = ST->getAlign();
19857 Ptr = LD->getBasePtr();
19858 VT = LD->getMemoryVT();
19859 Alignment = LD->getAlign();
19863 Ptr = ST->getBasePtr();
19864 VT = ST->getMemoryVT();
19865 Alignment = ST->getAlign();
19871 bool isLegal =
false;
19873 isLegal = Subtarget->hasMVEIntegerOps() &&
19875 Ptr.getNode(), VT, Alignment, isSEXTLoad, IsMasked,
19903 bool isSEXTLoad =
false, isNonExt;
19904 bool IsMasked =
false;
19906 VT = LD->getMemoryVT();
19907 Ptr = LD->getBasePtr();
19908 Alignment = LD->getAlign();
19911 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
19912 VT = ST->getMemoryVT();
19913 Ptr = ST->getBasePtr();
19914 Alignment = ST->getAlign();
19915 isNonExt = !ST->isTruncatingStore();
19917 VT = LD->getMemoryVT();
19918 Ptr = LD->getBasePtr();
19919 Alignment = LD->getAlign();
19924 VT = ST->getMemoryVT();
19925 Ptr = ST->getBasePtr();
19926 Alignment = ST->getAlign();
19927 isNonExt = !ST->isTruncatingStore();
19935 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
19936 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
19938 auto *
RHS = dyn_cast<ConstantSDNode>(
Op->getOperand(1));
19939 if (!
RHS ||
RHS->getZExtValue() != 4)
19941 if (Alignment <
Align(4))
19945 Base =
Op->getOperand(0);
19951 bool isLegal =
false;
19953 isLegal = Subtarget->hasMVEIntegerOps() &&
19986 const APInt &DemandedElts,
19988 unsigned Depth)
const {
19991 switch (
Op.getOpcode()) {
19998 if (
Op.getResNo() == 0) {
20024 case Intrinsic::arm_ldaex:
20025 case Intrinsic::arm_ldrex: {
20026 EVT VT = cast<MemIntrinsicSDNode>(
Op)->getMemoryVT();
20040 const APInt &Mask =
Op.getConstantOperandAPInt(2);
20041 Known.
Zero &= Mask;
20047 const SDValue &SrcSV =
Op.getOperand(0);
20053 "VGETLANE index out of bounds");
20058 EVT VT =
Op.getValueType();
20065 Known = Known.
sext(DstSz);
20067 Known = Known.
zext(DstSz);
20075 Known = KnownOp.
zext(32);
20115 EVT VT =
Op.getValueType();
20121 assert(VT == MVT::i32 &&
"Unexpected integer type");
20128 unsigned Mask =
C->getZExtValue();
20131 unsigned ShrunkMask = Mask & Demanded;
20132 unsigned ExpandedMask = Mask | ~Demanded;
20136 if (ShrunkMask == 0)
20142 if (ExpandedMask == ~0U)
20145 auto IsLegalMask = [ShrunkMask, ExpandedMask](
unsigned Mask) ->
bool {
20146 return (ShrunkMask & Mask) == ShrunkMask && (~ExpandedMask & Mask) == 0;
20148 auto UseMask = [Mask,
Op, VT, &TLO](
unsigned NewMask) ->
bool {
20149 if (NewMask == Mask)
20158 if (IsLegalMask(0xFF))
20159 return UseMask(0xFF);
20162 if (IsLegalMask(0xFFFF))
20163 return UseMask(0xFFFF);
20167 if (ShrunkMask < 256)
20168 return UseMask(ShrunkMask);
20172 if ((
int)ExpandedMask <= -2 && (
int)ExpandedMask >= -256)
20173 return UseMask(ExpandedMask);
20188 unsigned Depth)
const {
20189 unsigned Opc =
Op.getOpcode();
20197 if (
Op.getResNo() == 0 && !
Op->hasAnyUseOfValue(1) &&
20198 isa<ConstantSDNode>(
Op->getOperand(2))) {
20199 unsigned ShAmt =
Op->getConstantOperandVal(2);
20211 unsigned ModImm =
Op.getConstantOperandVal(1);
20212 unsigned EltBits = 0;
20214 if ((OriginalDemandedBits & Mask) == 0)
20220 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
20229 if (!Subtarget->hasV6Ops())
20235 SplitString(AsmStr, AsmPieces,
";\n");
20237 switch (AsmPieces.
size()) {
20238 default:
return false;
20240 AsmStr = AsmPieces[0];
20242 SplitString(AsmStr, AsmPieces,
" \t,");
20245 if (AsmPieces.
size() == 3 &&
20246 AsmPieces[0] ==
"rev" && AsmPieces[1] ==
"$0" && AsmPieces[2] ==
"$1" &&
20247 IA->getConstraintString().compare(0, 4,
"=l,l") == 0) {
20270 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20282 unsigned S = Constraint.
size();
20284 switch (Constraint[0]) {
20296 }
else if (S == 2) {
20297 switch (Constraint[0]) {
20314 Value *CallOperandVal =
info.CallOperandVal;
20317 if (!CallOperandVal)
20321 switch (*constraint) {
20327 if (Subtarget->isThumb())
20341using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20345 switch (Constraint.
size()) {
20348 switch (Constraint[0]) {
20350 if (Subtarget->isThumb())
20351 return RCPair(0U, &ARM::tGPRRegClass);
20352 return RCPair(0U, &ARM::GPRRegClass);
20354 if (Subtarget->isThumb())
20355 return RCPair(0U, &ARM::hGPRRegClass);
20359 return RCPair(0U, &ARM::tGPRRegClass);
20360 return RCPair(0U, &ARM::GPRRegClass);
20362 if (VT == MVT::Other)
20364 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20365 return RCPair(0U, &ARM::SPRRegClass);
20367 return RCPair(0U, &ARM::DPRRegClass);
20369 return RCPair(0U, &ARM::QPRRegClass);
20372 if (VT == MVT::Other)
20374 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20375 return RCPair(0U, &ARM::SPR_8RegClass);
20377 return RCPair(0U, &ARM::DPR_8RegClass);
20379 return RCPair(0U, &ARM::QPR_8RegClass);
20382 if (VT == MVT::Other)
20384 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20385 return RCPair(0U, &ARM::SPRRegClass);
20387 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20389 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20395 if (Constraint[0] ==
'T') {
20396 switch (Constraint[1]) {
20400 return RCPair(0U, &ARM::tGPREvenRegClass);
20402 return RCPair(0U, &ARM::tGPROddRegClass);
20411 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20412 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20421 std::vector<SDValue> &Ops,
20426 if (Constraint.
size() != 1)
20429 char ConstraintLetter = Constraint[0];
20430 switch (ConstraintLetter) {
20433 case 'I':
case 'J':
case 'K':
case 'L':
20434 case 'M':
case 'N':
case 'O':
20439 int64_t CVal64 =
C->getSExtValue();
20440 int CVal = (int) CVal64;
20443 if (CVal != CVal64)
20446 switch (ConstraintLetter) {
20450 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
20451 if (CVal >= 0 && CVal <= 65535)
20458 if (CVal >= 0 && CVal <= 255)
20460 }
else if (Subtarget->
isThumb2()) {
20479 if (CVal >= -255 && CVal <= -1)
20485 if (CVal >= -4095 && CVal <= 4095)
20498 }
else if (Subtarget->
isThumb2()) {
20521 if (CVal >= -7 && CVal < 7)
20523 }
else if (Subtarget->
isThumb2()) {
20546 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
20552 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
20560 if (CVal >= 0 && CVal <= 31)
20569 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
20578 if (Result.getNode()) {
20579 Ops.push_back(Result);
20589 "Unhandled Opcode in getDivRemLibcall");
20595 case MVT::i8: LC =
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
20596 case MVT::i16: LC =
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
20597 case MVT::i32: LC =
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
20598 case MVT::i64: LC =
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
20607 "Unhandled Opcode in getDivRemArgList");
20612 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
20613 EVT ArgVT =
N->getOperand(i).getValueType();
20615 Entry.Node =
N->getOperand(i);
20619 Args.push_back(Entry);
20630 "Register-based DivRem lowering only");
20631 unsigned Opcode =
Op->getOpcode();
20633 "Invalid opcode for Div/Rem lowering");
20635 EVT VT =
Op->getValueType(0);
20638 if (VT == MVT::i64 && isa<ConstantSDNode>(
Op.getOperand(1))) {
20657 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
20658 : Subtarget->hasDivideInARMMode();
20659 if (hasDivide &&
Op->getValueType(0).isSimple() &&
20660 Op->getSimpleValueType(0) == MVT::i32) {
20662 const SDValue Dividend =
Op->getOperand(0);
20663 const SDValue Divisor =
Op->getOperand(1);
20664 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
20668 SDValue Values[2] = {Div, Rem};
20700 EVT VT =
N->getValueType(0);
20702 if (VT == MVT::i64 && isa<ConstantSDNode>(
N->getOperand(1))) {
20706 Result[0], Result[1]);
20710 std::vector<Type*> RetTyParams;
20711 Type *RetTyElement;
20721 RetTyParams.push_back(RetTyElement);
20722 RetTyParams.push_back(RetTyElement);
20739 CallLoweringInfo CLI(DAG);
20743 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
20746 SDNode *ResNode = CallResult.first.getNode();
20761 "no-stack-arg-probe")) {
20763 cast<ConstantSDNode>(
Op.getOperand(2))->getMaybeAlignValue();
20772 SDValue Ops[2] = { SP, Chain };
20789 SDValue Ops[2] = { NewSP, Chain };
20794 bool IsStrict =
Op->isStrictFPOpcode();
20795 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20796 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20798 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
20799 "Unexpected type for custom-lowering FP_EXTEND");
20802 "With both FP DP and 16, any FP conversion is legal!");
20804 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
20805 "With FP16, 16 to 32 conversion is legal!");
20808 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
20813 Loc,
Op.getValueType(), SrcVal);
20826 MakeLibCallOptions CallOptions;
20828 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
20829 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
20830 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
20831 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
20835 {DstVT, MVT::Other}, {Chain, SrcVal});
20842 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20843 "Unexpected type for custom-lowering FP_EXTEND");
20844 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20849 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
20853 bool IsStrict =
Op->isStrictFPOpcode();
20855 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20857 EVT DstVT =
Op.getValueType();
20858 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20861 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
20862 "Unexpected type for custom-lowering FP_ROUND");
20865 "With both FP DP and 16, any FP conversion is legal!");
20870 if (SrcSz == 32 && Subtarget->hasFP16())
20875 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20876 "Unexpected type for custom-lowering FP_ROUND");
20877 MakeLibCallOptions CallOptions;
20880 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20892 if (v == 0xffffffff)
20904 bool ForCodeSize)
const {
20907 if (VT == MVT::f16 && Subtarget->hasFullFP16())
20909 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
20912 if (VT == MVT::f32)
20914 if (VT == MVT::f64 && Subtarget->hasFP64())
20925 unsigned Intrinsic)
const {
20926 switch (Intrinsic) {
20927 case Intrinsic::arm_neon_vld1:
20928 case Intrinsic::arm_neon_vld2:
20929 case Intrinsic::arm_neon_vld3:
20930 case Intrinsic::arm_neon_vld4:
20931 case Intrinsic::arm_neon_vld2lane:
20932 case Intrinsic::arm_neon_vld3lane:
20933 case Intrinsic::arm_neon_vld4lane:
20934 case Intrinsic::arm_neon_vld2dup:
20935 case Intrinsic::arm_neon_vld3dup:
20936 case Intrinsic::arm_neon_vld4dup: {
20939 auto &
DL =
I.getDataLayout();
20940 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20942 Info.ptrVal =
I.getArgOperand(0);
20944 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20945 Info.align = cast<ConstantInt>(AlignArg)->getMaybeAlignValue();
20950 case Intrinsic::arm_neon_vld1x2:
20951 case Intrinsic::arm_neon_vld1x3:
20952 case Intrinsic::arm_neon_vld1x4: {
20955 auto &
DL =
I.getDataLayout();
20956 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20958 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
20960 Info.align =
I.getParamAlign(
I.arg_size() - 1).valueOrOne();
20965 case Intrinsic::arm_neon_vst1:
20966 case Intrinsic::arm_neon_vst2:
20967 case Intrinsic::arm_neon_vst3:
20968 case Intrinsic::arm_neon_vst4:
20969 case Intrinsic::arm_neon_vst2lane:
20970 case Intrinsic::arm_neon_vst3lane:
20971 case Intrinsic::arm_neon_vst4lane: {
20974 auto &
DL =
I.getDataLayout();
20975 unsigned NumElts = 0;
20976 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20977 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20980 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
20983 Info.ptrVal =
I.getArgOperand(0);
20985 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20986 Info.align = cast<ConstantInt>(AlignArg)->getMaybeAlignValue();
20991 case Intrinsic::arm_neon_vst1x2:
20992 case Intrinsic::arm_neon_vst1x3:
20993 case Intrinsic::arm_neon_vst1x4: {
20996 auto &
DL =
I.getDataLayout();
20997 unsigned NumElts = 0;
20998 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20999 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
21002 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21005 Info.ptrVal =
I.getArgOperand(0);
21007 Info.align =
I.getParamAlign(0).valueOrOne();
21012 case Intrinsic::arm_mve_vld2q:
21013 case Intrinsic::arm_mve_vld4q: {
21016 Type *VecTy = cast<StructType>(
I.getType())->getElementType(1);
21017 unsigned Factor = Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
21019 Info.ptrVal =
I.getArgOperand(0);
21026 case Intrinsic::arm_mve_vst2q:
21027 case Intrinsic::arm_mve_vst4q: {
21030 Type *VecTy =
I.getArgOperand(1)->getType();
21031 unsigned Factor = Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
21033 Info.ptrVal =
I.getArgOperand(0);
21040 case Intrinsic::arm_mve_vldr_gather_base:
21041 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
21043 Info.ptrVal =
nullptr;
21049 case Intrinsic::arm_mve_vldr_gather_base_wb:
21050 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
21052 Info.ptrVal =
nullptr;
21058 case Intrinsic::arm_mve_vldr_gather_offset:
21059 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
21061 Info.ptrVal =
nullptr;
21063 unsigned MemSize = cast<ConstantInt>(
I.getArgOperand(2))->getZExtValue();
21070 case Intrinsic::arm_mve_vstr_scatter_base:
21071 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
21073 Info.ptrVal =
nullptr;
21079 case Intrinsic::arm_mve_vstr_scatter_base_wb:
21080 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
21082 Info.ptrVal =
nullptr;
21088 case Intrinsic::arm_mve_vstr_scatter_offset:
21089 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
21091 Info.ptrVal =
nullptr;
21093 unsigned MemSize = cast<ConstantInt>(
I.getArgOperand(3))->getZExtValue();
21100 case Intrinsic::arm_ldaex:
21101 case Intrinsic::arm_ldrex: {
21102 auto &
DL =
I.getDataLayout();
21103 Type *ValTy =
I.getParamElementType(0);
21106 Info.ptrVal =
I.getArgOperand(0);
21108 Info.align =
DL.getABITypeAlign(ValTy);
21112 case Intrinsic::arm_stlex:
21113 case Intrinsic::arm_strex: {
21114 auto &
DL =
I.getDataLayout();
21115 Type *ValTy =
I.getParamElementType(1);
21118 Info.ptrVal =
I.getArgOperand(1);
21120 Info.align =
DL.getABITypeAlign(ValTy);
21124 case Intrinsic::arm_stlexd:
21125 case Intrinsic::arm_strexd:
21127 Info.memVT = MVT::i64;
21128 Info.ptrVal =
I.getArgOperand(2);
21134 case Intrinsic::arm_ldaexd:
21135 case Intrinsic::arm_ldrexd:
21137 Info.memVT = MVT::i64;
21138 Info.ptrVal =
I.getArgOperand(0);
21158 if (Bits == 0 || Bits > 32)
21164 unsigned Index)
const {
21174 if (!Subtarget->hasDataBarrier()) {
21178 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
21213 if (Subtarget->preferISHSTBarriers())
21246 bool has64BitAtomicStore;
21248 has64BitAtomicStore =
false;
21249 else if (Subtarget->isThumb())
21250 has64BitAtomicStore = Subtarget->hasV7Ops();
21252 has64BitAtomicStore = Subtarget->hasV6Ops();
21254 unsigned Size = SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21268 bool has64BitAtomicLoad;
21270 has64BitAtomicLoad =
false;
21271 else if (Subtarget->isThumb())
21272 has64BitAtomicLoad = Subtarget->hasV7Ops();
21274 has64BitAtomicLoad = Subtarget->hasV6Ops();
21291 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21292 else if (Subtarget->isThumb())
21293 hasAtomicRMW = Subtarget->hasV7Ops();
21295 hasAtomicRMW = Subtarget->hasV6Ops();
21296 if (
Size <= (Subtarget->
isMClass() ? 32U : 64U) && hasAtomicRMW) {
21319 bool HasAtomicCmpXchg;
21321 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21322 else if (Subtarget->isThumb())
21323 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21325 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21327 HasAtomicCmpXchg &&
Size <= (Subtarget->
isMClass() ? 32U : 64U))
21334 return InsertFencesForAtomic;
21347 M.getOrInsertGlobal(
"__security_cookie",
21355 F->addParamAttr(0, Attribute::AttrKind::InReg);
21361 return M.getGlobalVariable(
"__security_cookie");
21368 return M.getFunction(
"__security_check_cookie");
21373 unsigned &
Cost)
const {
21375 if (!Subtarget->hasNEON())
21387 if (!isa<ConstantInt>(
Idx))
21402 return Subtarget->hasV6T2Ops();
21406 return Subtarget->hasV6T2Ops();
21411 if (!Subtarget->hasV7Ops())
21417 if (!Mask || Mask->getValue().getBitWidth() > 32u)
21419 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
21444 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
21456 Lo, Builder.
CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
21459 Type *Tys[] = {
Addr->getType() };
21460 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
21464 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
21470 if (!Subtarget->hasV7Ops())
21486 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
21496 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
21497 Type *Tys[] = {
Addr->getType() };
21519 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
21526 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
21529 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
21537 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
21545 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
21548 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
21553 if (Subtarget->hasNEON() && VecSize == 64)
21555 return VecSize % 128 == 0;
21559 if (Subtarget->hasNEON())
21561 if (Subtarget->hasMVEIntegerOps())
21581 "Invalid interleave factor");
21582 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
21584 "Unmatched number of shufflevectors and indices");
21586 auto *VecTy = cast<FixedVectorType>(Shuffles[0]->
getType());
21587 Type *EltTy = VecTy->getElementType();
21610 if (NumLoads > 1) {
21614 VecTy->getNumElements() / NumLoads);
21619 auto createLoadIntrinsic = [&](
Value *BaseAddr) {
21620 if (Subtarget->hasNEON()) {
21622 Type *Tys[] = {VecTy, PtrTy};
21623 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
21624 Intrinsic::arm_neon_vld3,
21625 Intrinsic::arm_neon_vld4};
21634 assert((Factor == 2 || Factor == 4) &&
21635 "expected interleave factor of 2 or 4 for MVE");
21637 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
21639 Type *Tys[] = {VecTy, PtrTy};
21653 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
21658 VecTy->getNumElements() * Factor);
21660 CallInst *VldN = createLoadIntrinsic(BaseAddr);
21664 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
21666 unsigned Index = Indices[i];
21676 SubVecs[SV].push_back(SubVec);
21685 auto &SubVec = SubVecs[SVI];
21688 SVI->replaceAllUsesWith(WideVec);
21722 unsigned Factor)
const {
21724 "Invalid interleave factor");
21726 auto *VecTy = cast<FixedVectorType>(SVI->
getType());
21727 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
21729 unsigned LaneLen = VecTy->getNumElements() / Factor;
21730 Type *EltTy = VecTy->getElementType();
21734 Align Alignment = SI->getAlign();
21751 Type *IntTy =
DL.getIntPtrType(EltTy);
21763 Value *BaseAddr = SI->getPointerOperand();
21765 if (NumStores > 1) {
21768 LaneLen /= NumStores;
21776 auto createStoreIntrinsic = [&](
Value *BaseAddr,
21778 if (Subtarget->hasNEON()) {
21779 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
21780 Intrinsic::arm_neon_vst3,
21781 Intrinsic::arm_neon_vst4};
21782 Type *PtrTy = Builder.
getPtrTy(SI->getPointerAddressSpace());
21783 Type *Tys[] = {PtrTy, SubVecTy};
21791 assert((Factor == 2 || Factor == 4) &&
21792 "expected interleave factor of 2 or 4 for MVE");
21794 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
21795 Type *PtrTy = Builder.
getPtrTy(SI->getPointerAddressSpace());
21796 Type *Tys[] = {PtrTy, SubVecTy};
21801 for (
unsigned F = 0;
F < Factor;
F++) {
21809 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
21812 if (StoreCount > 0)
21814 BaseAddr, LaneLen * Factor);
21819 for (
unsigned i = 0; i < Factor; i++) {
21820 unsigned IdxI = StoreCount * LaneLen * Factor + i;
21821 if (Mask[IdxI] >= 0) {
21825 unsigned StartMask = 0;
21826 for (
unsigned j = 1; j < LaneLen; j++) {
21827 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
21828 if (Mask[IdxJ * Factor + IdxI] >= 0) {
21829 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
21844 createStoreIntrinsic(BaseAddr, Shuffles);
21859 if (
auto *ST = dyn_cast<StructType>(Ty)) {
21860 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
21864 Members += SubMembers;
21866 }
else if (
auto *AT = dyn_cast<ArrayType>(Ty)) {
21870 Members += SubMembers * AT->getNumElements();
21881 }
else if (
auto *VT = dyn_cast<VectorType>(Ty)) {
21888 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
21890 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
21892 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
21905 return (Members > 0 && Members <= 4);
21911 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
21913 return ABITypeAlign;
21918 assert(StackAlign &&
"data layout string is missing stack alignment");
21919 return std::min(ABITypeAlign, *StackAlign);
21928 if (getEffectiveCallingConv(CallConv, isVarArg) !=
21938 return IsHA || IsIntArray;
21942 const Constant *PersonalityFn)
const {
21949 const Constant *PersonalityFn)
const {
21961void ARMTargetLowering::insertCopiesSplitCSR(
21965 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
21975 RC = &ARM::GPRRegClass;
21976 else if (ARM::DPRRegClass.
contains(*
I))
21977 RC = &ARM::DPRRegClass;
21987 assert(Entry->getParent()->getFunction().hasFnAttribute(
21988 Attribute::NoUnwind) &&
21989 "Function should be nounwind in insertCopiesSplitCSR!");
21990 Entry->addLiveIn(*
I);
21995 for (
auto *Exit : Exits)
21997 TII->get(TargetOpcode::COPY), *
I)
22008 return Subtarget->hasMVEIntegerOps();
22013 auto *VTy = dyn_cast<FixedVectorType>(Ty);
22018 unsigned NumElements = VTy->getNumElements();
22025 if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy())
22026 return Subtarget->hasMVEFloatOps();
22031 return Subtarget->hasMVEIntegerOps() &&
22032 (ScalarTy->isIntegerTy(8) || ScalarTy->isIntegerTy(16) ||
22033 ScalarTy->isIntegerTy(32));
22045 assert(TyWidth >= 128 &&
"Width of vector type must be at least 128 bits");
22047 if (TyWidth > 128) {
22052 ArrayRef<int> UpperSplitMask(&SplitSeqVec[Stride], Stride);
22054 auto *LowerSplitA =
B.CreateShuffleVector(InputA, LowerSplitMask);
22055 auto *LowerSplitB =
B.CreateShuffleVector(InputB, LowerSplitMask);
22056 auto *UpperSplitA =
B.CreateShuffleVector(InputA, UpperSplitMask);
22057 auto *UpperSplitB =
B.CreateShuffleVector(InputB, UpperSplitMask);
22058 Value *LowerSplitAcc =
nullptr;
22059 Value *UpperSplitAcc =
nullptr;
22062 LowerSplitAcc =
B.CreateShuffleVector(
Accumulator, LowerSplitMask);
22063 UpperSplitAcc =
B.CreateShuffleVector(
Accumulator, UpperSplitMask);
22067 B, OperationType, Rotation, LowerSplitA, LowerSplitB, LowerSplitAcc);
22069 B, OperationType, Rotation, UpperSplitA, UpperSplitB, UpperSplitAcc);
22072 return B.CreateShuffleVector(LowerSplitInt, UpperSplitInt, JoinMask);
22079 ConstRotation = ConstantInt::get(IntTy, (
int)Rotation);
22082 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmlaq, Ty,
22084 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmulq, Ty,
22085 {ConstRotation, InputB, InputA});
22090 auto *ConstHalving = ConstantInt::get(IntTy, 1);
22093 ConstRotation = ConstantInt::get(IntTy, 0);
22095 ConstRotation = ConstantInt::get(IntTy, 1);
22097 if (!ConstRotation)
22100 return B.CreateIntrinsic(Intrinsic::arm_mve_vcaddq, Ty,
22101 {ConstHalving, ConstRotation, InputA, InputB});
unsigned const MachineRegisterInfo * MRI
static bool isAddSubSExt(SDValue N, SelectionDAG &DAG)
static bool isVShiftRImm(SDValue Op, EVT VT, bool isNarrow, int64_t &Cnt)
isVShiftRImm - Check if this is a valid build_vector for the immediate operand of a vector shift righ...
static bool isExtendedBUILD_VECTOR(SDValue N, SelectionDAG &DAG, bool isSigned)
static bool isZeroExtended(SDValue N, SelectionDAG &DAG)
static const MCPhysReg GPRArgRegs[]
static SDValue GeneratePerfectShuffle(unsigned ID, SDValue V1, SDValue V2, unsigned PFEntry, SDValue LHS, SDValue RHS, SelectionDAG &DAG, const SDLoc &dl)
GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit the specified operations t...
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.
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 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 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 const MCPhysReg GPRArgRegs[]
static SDValue PerformADDCombineWithOperands(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombineWithOperands - Try DAG combinations for an ADD with operands N0 and N1.
static SDValue PromoteMVEPredVector(SDLoc dl, SDValue Pred, EVT VT, SelectionDAG &DAG)
static bool isVZIPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue PerformORCombineToSMULWBT(SDNode *OR, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool isVTRN_v_undef_Mask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
isVTRN_v_undef_Mask - Special case of isVTRNMask for canonical form of "vector_shuffle v,...
static SDValue LowerUDIV(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue FindBFIToCombineWith(SDNode *N)
static SDValue LowerADDSUBSAT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue ConvertCarryFlagToBooleanCarry(SDValue Flags, EVT VT, SelectionDAG &DAG)
static void checkVSELConstraints(ISD::CondCode CC, ARMCC::CondCodes &CondCode, bool &swpCmpOps, bool &swpVselOps)
static void ReplaceLongIntrinsic(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isS16(const SDValue &Op, SelectionDAG &DAG)
static bool isSRA16(const SDValue &Op)
constexpr MVT FlagsVT
Value type used for "flags" operands / results (either CPSR or FPSCR_NZCV).
static SDValue AddCombineBUILD_VECTORToVPADDL(SDNode *N, SDValue N0, SDValue N1, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerVECTOR_SHUFFLEUsingMovs(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue LowerInterruptReturn(SmallVectorImpl< SDValue > &RetOps, const SDLoc &DL, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerSDIV_v4i8(SDValue X, SDValue Y, const SDLoc &dl, SelectionDAG &DAG)
static void expandf64Toi32(SDValue Op, SelectionDAG &DAG, SDValue &RetVal1, SDValue &RetVal2)
static SDValue LowerCONCAT_VECTORS_i1(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerCTTZ(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isSHL16(const SDValue &Op)
static bool isVEXTMask(ArrayRef< int > M, EVT VT, bool &ReverseVEXT, unsigned &Imm)
static SDValue PerformMVEVLDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool isTruncMask(ArrayRef< int > M, EVT VT, bool Top, bool SingleSource)
static SDValue PerformADDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDCombine - Target-specific dag combine xforms for ISD::ADD.
static unsigned getLdOpcode(unsigned LdSize, bool IsThumb1, bool IsThumb2)
Return the load opcode for a given load size.
static bool isLegalT2AddressImmediate(int64_t V, EVT VT, const ARMSubtarget *Subtarget)
static bool isLegalMVEShuffleOp(unsigned PFEntry)
static SDValue PerformSignExtendInregCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformShuffleVMOVNCombine(ShuffleVectorSDNode *N, SelectionDAG &DAG)
static bool isVUZPMask(ArrayRef< int > M, EVT VT, unsigned &WhichResult)
static SDValue PerformVECTOR_SHUFFLECombine(SDNode *N, SelectionDAG &DAG)
PerformVECTOR_SHUFFLECombine - Target-specific dag combine xforms for ISD::VECTOR_SHUFFLE.
static SDValue SkipExtensionForVMULL(SDNode *N, SelectionDAG &DAG)
SkipExtensionForVMULL - For a node that is a SIGN_EXTEND, ZERO_EXTEND, ANY_EXTEND,...
static bool isVMOVNTruncMask(ArrayRef< int > M, EVT ToVT, bool rev)
static SDValue PerformVQMOVNCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static MachineBasicBlock * OtherSucc(MachineBasicBlock *MBB, MachineBasicBlock *Succ)
static SDValue LowerVecReduceMinMax(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformFPExtendCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformAddcSubcCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue PerformVSELECTCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static TargetLowering::ArgListTy getDivRemArgList(const SDNode *N, LLVMContext *Context, const ARMSubtarget *Subtarget)
static SDValue PerformVECREDUCE_ADDCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue getZeroVector(EVT VT, SelectionDAG &DAG, const SDLoc &dl)
getZeroVector - Returns a vector of specified type with all zero elements.
static SDValue LowerAtomicLoadStore(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSplittingToNarrowingStores(StoreSDNode *St, SelectionDAG &DAG)
static bool getT2IndexedAddressParts(SDNode *Ptr, EVT VT, bool isSEXTLoad, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
static ARMCC::CondCodes getVCMPCondCode(SDValue N)
static cl::opt< bool > ARMInterworking("arm-interworking", cl::Hidden, cl::desc("Enable / disable ARM interworking (for debugging only)"), cl::init(true))
static void ReplaceREADCYCLECOUNTER(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformORCombineToBFI(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool isConditionalZeroOrAllOnes(SDNode *N, bool AllOnes, SDValue &CC, bool &Invert, SDValue &OtherOp, SelectionDAG &DAG)
static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue PerformVSetCCToVCTPCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerBUILD_VECTORToVIDUP(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isZeroVector(SDValue N)
static SDValue PerformAddeSubeCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static void ReplaceCMP_SWAP_64Results(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG)
static bool isLowerSaturate(const SDValue LHS, const SDValue RHS, const SDValue TrueVal, const SDValue FalseVal, const ISD::CondCode CC, const SDValue K)
static SDValue LowerPredicateLoad(SDValue Op, SelectionDAG &DAG)
static void emitPostSt(MachineBasicBlock *BB, MachineBasicBlock::iterator Pos, const TargetInstrInfo *TII, const DebugLoc &dl, unsigned StSize, unsigned Data, unsigned AddrIn, unsigned AddrOut, bool IsThumb1, bool IsThumb2)
Emit a post-increment store operation with given size.
static bool isVMOVNMask(ArrayRef< int > M, EVT VT, bool Top, bool SingleSource)
static SDValue CombineBaseUpdate(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
CombineBaseUpdate - Target-specific DAG combine function for VLDDUP, NEON load/store intrinsics,...
static SDValue LowerSaturatingConditional(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSubCSINCCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformVMOVRRDCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVMOVRRDCombine - Target-specific dag combine xforms for ARMISD::VMOVRRD.
static SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformCSETCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformVMOVNCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue PerformInsertSubvectorCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static SDValue LowerVectorExtend(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue WinDBZCheckDenominator(SelectionDAG &DAG, SDNode *N, SDValue InChain)
static SDValue LowerVECTOR_SHUFFLEv8i8(SDValue Op, ArrayRef< int > ShuffleMask, SelectionDAG &DAG)
static SDValue PerformVMULCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformVMULCombine Distribute (A + B) * C to (A * C) + (B * C) to take advantage of the special multi...
static SDValue LowerMUL(SDValue Op, SelectionDAG &DAG)
static SDValue PerformBFICombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformORCombine - Target-specific dag combine xforms for ISD::OR.
static SDValue LowerMLOAD(SDValue Op, SelectionDAG &DAG)
static SDValue PerformTruncatingStoreCombine(StoreSDNode *St, SelectionDAG &DAG)
static unsigned SelectPairHalf(unsigned Elements, ArrayRef< int > Mask, unsigned Index)
static void emitPostLd(MachineBasicBlock *BB, MachineBasicBlock::iterator Pos, const TargetInstrInfo *TII, const DebugLoc &dl, unsigned LdSize, unsigned Data, unsigned AddrIn, unsigned AddrOut, bool IsThumb1, bool IsThumb2)
Emit a post-increment load operation with given size.
static SDValue TryDistrubutionADDVecReduce(SDNode *N, SelectionDAG &DAG)
static bool isValidBaseUpdate(SDNode *N, SDNode *User)
static SDValue IsSingleInstrConstant(SDValue N, SelectionDAG &DAG, const ARMSubtarget *ST, const SDLoc &dl)
static bool IsQRMVEInstruction(const SDNode *N, const SDNode *Op)
static SDValue PerformMinMaxToSatCombine(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformXORCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static bool getMVEIndexedAddressParts(SDNode *Ptr, EVT VT, Align Alignment, bool isSEXTLoad, bool IsMasked, bool isLE, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
std::pair< unsigned, const TargetRegisterClass * > RCPair
static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, TargetLowering::DAGCombinerInfo &DCI, bool AllOnes=false)
static SDValue PerformExtendCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST)
PerformExtendCombine - Target-specific DAG combining for ISD::SIGN_EXTEND, ISD::ZERO_EXTEND,...
static SDValue LowerSDIV(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
cl::opt< unsigned > MVEMaxSupportedInterleaveFactor("mve-max-interleave-factor", cl::Hidden, cl::desc("Maximum interleave factor for MVE VLDn to generate."), cl::init(2))
static SDValue isVMOVModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, unsigned SplatBitSize, SelectionDAG &DAG, const SDLoc &dl, EVT &VT, EVT VectorVT, VMOVModImmType type)
isVMOVModifiedImm - Check if the specified splat value corresponds to a valid vector constant for a N...
static SDValue LowerBuildVectorOfFPExt(SDValue BV, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue CombineVMOVDRRCandidateWithVecOp(const SDNode *BC, SelectionDAG &DAG)
BC is a bitcast that is about to be turned into a VMOVDRR.
static SDValue promoteToConstantPool(const ARMTargetLowering *TLI, const GlobalValue *GV, SelectionDAG &DAG, EVT PtrVT, const SDLoc &dl)
static unsigned isNEONTwoResultShuffleMask(ArrayRef< int > ShuffleMask, EVT VT, unsigned &WhichResult, bool &isV_UNDEF)
Check if ShuffleMask is a NEON two-result shuffle (VZIP, VUZP, VTRN), and return the corresponding AR...
static bool BitsProperlyConcatenate(const APInt &A, const APInt &B)
static bool getARMIndexedAddressParts(SDNode *Ptr, EVT VT, bool isSEXTLoad, SDValue &Base, SDValue &Offset, bool &isInc, SelectionDAG &DAG)
static SDValue LowerVecReduce(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static SDValue LowerVectorINT_TO_FP(SDValue Op, SelectionDAG &DAG)
static bool TryCombineBaseUpdate(struct BaseUpdateTarget &Target, struct BaseUpdateUser &User, bool SimpleConstIncOnly, TargetLowering::DAGCombinerInfo &DCI)
static bool allUsersAreInFunction(const Value *V, const Function *F)
Return true if all users of V are within function F, looking through ConstantExprs.
static bool isSingletonVEXTMask(ArrayRef< int > M, EVT VT, unsigned &Imm)
static SDValue PerformVMOVDRRCombine(SDNode *N, SelectionDAG &DAG)
PerformVMOVDRRCombine - Target-specific dag combine xforms for ARMISD::VMOVDRR.
static bool isLowerSaturatingConditional(const SDValue &Op, SDValue &V, SDValue &SatK)
static bool isLegalAddressImmediate(int64_t V, EVT VT, const ARMSubtarget *Subtarget)
isLegalAddressImmediate - Return true if the integer value can be used as the offset of the target ad...
static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG, const ARMSubtarget *ST)
static bool isLegalT1AddressImmediate(int64_t V, EVT VT)
static SDValue CombineANDShift(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
static SDValue LowerSETCCCARRY(SDValue Op, SelectionDAG &DAG)
static SDValue PerformSHLSimplify(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *ST)
static SDValue PerformADDECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI, const ARMSubtarget *Subtarget)
PerformADDECombine - Target-specific dag combine transform from ARMISD::ADDC, ARMISD::ADDE,...
static SDValue PerformReduceShuffleCombine(SDNode *N, SelectionDAG &DAG)
static SDValue PerformUMLALCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerSTORE(SDValue Op, 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 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 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.
BlockVerifier::State From
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Analysis containing CSE Info
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...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
static Function * getFunction(Constant *C)
static bool isSigned(unsigned int Opcode)
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
std::pair< Value *, Value * > ShuffleOps
We are building a shuffle to create V, which is a sequence of insertelement, extractelement pairs.
static Value * LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP)
Emit the code to lower ctpop of V before the specified instruction IP.
loop Loop Strength Reduction
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 found DebugLoc that has a DILocation, given a range of instructions.
unsigned const TargetRegisterInfo * TRI
uint64_t IntrinsicInst * II
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
PowerPC Reduce CR logical Operation
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
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 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)
bool getExactInverse(APFloat *inv) const
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.
uint64_t getZExtValue() const
Get zero extended value.
unsigned popcount() const
Count the number of bits set.
APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
unsigned getActiveBits() const
Compute the number of active bits in the value.
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 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.
virtual const ARMBaseRegisterInfo & getRegisterInfo() const =0
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 shouldSignReturnAddress() const
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
bool isTargetMachO() const
bool isTargetAEABI() const
bool supportsTailCall() const
const Triple & getTargetTriple() const
const ARMBaseInstrInfo * getInstrInfo() const override
bool isThumb1Only() const
bool hasFPARMv8Base() const
bool isTargetWindows() const
bool isGVIndirectSymbol(const GlobalValue *GV) const
True if the GV will be accessed via an indirect symbol.
const ARMTargetLowering * getTargetLowering() const override
bool isTargetDarwin() const
const ARMBaseRegisterInfo * getRegisterInfo() const override
bool isTargetAndroid() const
bool isTargetCOFF() const
bool isTargetGNUAEABI() const
bool isTargetWatchOS() const
unsigned getPreferBranchLogAlignment() const
bool useNEONForSinglePrecisionFP() const
const InstrItineraryData * getInstrItineraryData() const override
getInstrItins - Return the instruction itineraries based on subtarget selection.
bool isTargetWatchABI() const
bool hasAnyDataBarrier() const
bool isTargetDriverKit() const
bool allowsUnalignedMem() const
bool isTargetMuslAEABI() const
bool isTargetLinux() const
bool isTargetHardFloat() const
Align getDualLoadStoreAlignment() const
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...
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 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,...
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...
Function * getSSPStackGuardCheck(const Module &M) const override
If the target has a standard stack protection check function that performs validation and error handl...
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.
void insertSSPDeclarations(Module &M) const override
Inserts necessary declarations for SSP (stack protection) purpose.
SDValue PerformIntrinsicCombine(SDNode *N, DAGCombinerInfo &DCI) const
PerformIntrinsicCombine - ARM-specific DAG combining for intrinsics.
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...
bool ExpandInlineAsm(CallInst *CI) const override
This hook allows the target to expand an inline asm call to be explicit llvm code if it wants to.
SDValue PerformCMOVCombine(SDNode *N, SelectionDAG &DAG) const
PerformCMOVCombine - Target-specific DAG combining for ARMISD::CMOV.
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.
Value * getSDagStackGuard(const Module &M) const override
Return the variable that's previously inserted by insertSSPDeclarations, if any, otherwise return nul...
SDValue PerformMVEExtCombine(SDNode *N, DAGCombinerInfo &DCI) const
bool shouldFoldConstantShiftPairToMask(const SDNode *N, CombineLevel Level) const override
Return true if it is profitable to fold a pair of shifts into a mask.
bool shouldFoldSelectWithIdentityConstant(unsigned BinOpcode, EVT VT) const override
Return true if pulling a binary operation into a select with an identity constant is profitable.
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
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo) const override
createFastISel - This method returns a target specific FastISel object, or null if the target does no...
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
This method should be implemented by targets that mark instructions with the 'hasPostISelHook' flag.
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
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 getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I, MachineFunction &MF, unsigned Intrinsic) const override
getTgtMemIntrinsic - Represent NEON load and store intrinsics as MemIntrinsicNodes.
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...
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.
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 ...
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 isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
bool isCheapToSpeculateCttz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic cttz.
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
bool isCheapToSpeculateCtlz(Type *Ty) const override
Return true if it is cheap to speculate a call to intrinsic ctlz.
bool targetShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, TargetLoweringOpt &TLO) const override
bool lowerInterleavedStore(StoreInst *SI, ShuffleVectorInst *SVI, unsigned Factor) const override
Lower an interleaved store into a vstN intrinsic.
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.
SDValue PerformBRCONDCombine(SDNode *N, SelectionDAG &DAG) const
PerformBRCONDCombine - Target-specific DAG combining for ARMISD::BRCOND.
const char * getTargetNodeName(unsigned Opcode) const override
This method returns the name of a target specific DAG node.
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.
EVT getOptimalMemOpType(const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
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...
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
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 lowerInterleavedLoad(LoadInst *LI, ArrayRef< ShuffleVectorInst * > Shuffles, ArrayRef< unsigned > Indices, unsigned Factor) const override
Lower an interleaved load into a vldN intrinsic.
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.
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.
This class represents an incoming formal argument to a Function.
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
bool hasFnAttr(Attribute::AttrKind Kind) const
Return true if the attribute exists for the function.
static Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
static BaseIndexOffset match(const SDNode *N, const SelectionDAG &DAG)
Parses tree in N for base, index, offset addresses.
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
The address of a basic block.
static BranchProbability getZero()
A "pseudo-class" with methods for operating on BUILD_VECTORs.
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.
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 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.
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 ...
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)
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
bool isMustTailCall() const
Tests if this call site must be tail call optimized.
Value * getCalledOperand() const
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
const APInt & getAPIntValue() const
int64_t getSExtValue() const
This is an important base class in LLVM.
This class represents an Operation in the Expression.
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.
TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
Align getPreferredAlign(const GlobalVariable *GV) const
Returns the preferred alignment of the specified global.
StringRef getPrivateGlobalPrefix() const
Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Diagnostic information for unsupported feature in backend.
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 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.
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.
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.
Value * CreateZExtOrBitCast(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, Instruction *FMFSource=nullptr, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
BasicBlock * GetInsertBlock() const
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
Value * CreateTruncOrBitCast(Value *V, Type *DestTy, const Twine &Name="")
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
std::optional< unsigned > getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const
Return the cycle for the given class and operand.
bool isEmpty() const
Returns true if there are no itineraries.
bool hasAtomicStore() const LLVM_READONLY
Return true if this atomic instruction stores to memory.
const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
static bool LowerToByteSwap(CallInst *CI)
Try to replace a call instruction with a call to a bswap intrinsic.
This is an important class for using LLVM in a threaded context.
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.
An instruction for reading from memory.
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
Value * getPointerOperand()
Align getAlign() const
Return the alignment of the access that is being performed.
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.
unsigned getSchedClass() const
Return the scheduling class for this instruction.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specified operand constraint if it is present.
Wrapper class representing physical registers. Should be passed by value.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
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 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()
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.
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.
bool canFallThrough()
Return true if the block can implicitly transfer control to the block after it by falling off the end...
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
pred_iterator pred_begin()
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.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
iterator_range< succ_iterator > successors()
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 '...
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.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
void computeMaxCallFrameSize(MachineFunction &MF, std::vector< MachineBasicBlock::iterator > *FrameSDOps=nullptr)
Computes the maximum size of a callframe.
void setAdjustsStack(bool V)
int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
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.
MachineFunctionProperties & reset(Property P)
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.
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)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
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 & 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 & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addJumpTableIndex(unsigned Idx, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
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.
const MachineOperand & getOperand(unsigned i) const
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.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
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.
void setIsDef(bool Val=true)
Change a def to a use, or a use to a def.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
This class is used to represent an MLOAD node.
This class is used to represent an MSTORE node.
This SDNode is used for target intrinsics that touch memory and need an associated MachineMemOperand.
This is an abstract virtual class for memory operations.
AAMDNodes getAAInfo() const
Returns the AA info that describes the dereference.
Align getOriginalAlign() const
Returns alignment and volatility of the memory access.
bool isSimple() const
Returns true if the memory operation is neither atomic or volatile.
MachineMemOperand * getMemOperand() const
Return a 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.
virtual void print(raw_ostream &OS, const Module *M) const
print - Print out the internal state of the pass.
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.
bool isOnlyUserOf(const SDNode *N) const
Return true if this node is the only use of N.
iterator_range< use_iterator > uses()
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.
bool isPredecessorOf(const SDNode *N) const
Return true if this node is a predecessor of N.
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.
bool isUndef() const
Return true if the type of the node type undefined.
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...
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)
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)
SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
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...
SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
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),...
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
SDValue UnrollVectorOp(SDNode *N, unsigned ResNE=0)
Utility function used by legalize and lowering to "unroll" a vector operation by splitting out the sc...
bool haveNoCommonBitsSet(SDValue A, SDValue B) const
Return true if A and B have no common bits set.
SDValue getRegister(Register Reg, EVT VT)
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,...
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.
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.
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)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand * > NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
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
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)
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())
void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
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.
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.
SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
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 ...
SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
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...
SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
SDValue getSelectCC(const SDLoc &DL, SDValue LHS, SDValue RHS, SDValue True, SDValue False, ISD::CondCode Cond)
Helper function to make it easier to build SelectCC's if you just have an ISD::CondCode instead of an...
SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
SDValue getValueType(EVT)
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)
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.
SDValue getVectorIdxConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
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.
SDValue getRegisterMask(const uint32_t *RegMask)
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...
SDValue getCondCode(ISD::CondCode Cond)
void addCallSiteInfo(const SDNode *Node, CallSiteInfo &&CallInfo)
Set CallSiteInfo to be associated with Node.
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
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=0, const AAMDNodes &AAInfo=AAMDNodes())
Creates a MemIntrinsicNode that may produce a result and takes a list of operands.
SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
SDNode * getNodeIfExists(unsigned Opcode, SDVTList VTList, ArrayRef< SDValue > Ops, const SDNodeFlags Flags)
Get the specified node if it's already available, or else return NULL.
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.
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)
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.
SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
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 void getShuffleMask(const Constant *Mask, SmallVectorImpl< int > &Result)
Convert the input shuffle mask operand to a vector of integers.
static 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...
static bool isSplatMask(const int *Mask, EVT VT)
int getMaskElt(unsigned Idx) const
int getSplatIndex() const
ArrayRef< int > getMask() const
void reserve(size_type NumEntries)
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.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
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.
const unsigned char * bytes_begin() const
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
static 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...
void setCmpLibcallCC(RTLIB::Libcall Call, ISD::CondCode CC)
Override the default CondCode to be used to test the result of the comparison libcall against zero.
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const
Get the CallingConv that should be used for the specified libcall.
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
void setLibcallCallingConv(RTLIB::Libcall Call, CallingConv::ID CC)
Set the CallingConv that should be used for the specified libcall.
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...
virtual Value * getSDagStackGuard(const Module &M) const
Return the variable that's previously inserted by insertSSPDeclarations, if any, otherwise return nul...
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.
virtual Function * getSSPStackGuardCheck(const Module &M) const
If the target has a standard stack protection check function that performs validation and error handl...
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 setLibcallName(RTLIB::Libcall Call, const char *Name)
Rename the default libcall routine name for the specified libcall.
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...
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...
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 ...
const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.
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.
virtual void insertSSPDeclarations(Module &M) const
Inserts necessary declarations for SSP (stack protection) purpose.
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.
std::pair< SDValue, SDValue > makeLibCall(SelectionDAG &DAG, RTLIB::Libcall LC, EVT RetVT, ArrayRef< SDValue > Ops, MakeLibCallOptions CallOptions, const SDLoc &dl, SDValue Chain=SDValue()) const
Returns a pair of (return value, chain).
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...
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.
bool verifyReturnAddressArgumentIsConstant(SDValue Op, SelectionDAG &DAG) const
bool isConstTrueVal(SDValue N) const
Return if the N is a constant or constant vector equal to the true value from getBooleanContents().
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
Primary interface to the complete machine description for the target machine.
TLSModel::Model getTLSModel(const GlobalValue *GV) const
Returns the TLS model which should be used for the given global variable.
const Triple & getTargetTriple() const
bool useEmulatedTLS() const
Returns true if this target uses emulated TLS.
virtual const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
unsigned EnableFastISel
EnableFastISel - This flag enables fast-path instruction selection which trades away generated code q...
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
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 isOSVersionLT(unsigned Major, unsigned Minor=0, unsigned Micro=0) const
Helper function for doing comparisons against version numbers included in the target triple.
bool isWindowsMSVCEnvironment() const
Checks if the environment could be MSVC.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
bool isVectorTy() const
True if this is an instance of VectorType.
bool isArrayTy() const
True if this is an instance of ArrayType.
bool isPointerTy() const
True if this is an instance of PointerType.
Type * getArrayElementType() const
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
static Type * getVoidTy(LLVMContext &C)
static 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.
static IntegerType * getInt8Ty(LLVMContext &C)
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
static IntegerType * getInt32Ty(LLVMContext &C)
static IntegerType * getInt64Ty(LLVMContext &C)
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.
TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
unsigned getOperandNo() const
Return the operand # of this use in its User.
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
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 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
const unsigned FPReservedBits
const unsigned RoundingBitsPos
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo)
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.
@ 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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
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.
@ 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).
@ 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,...
@ 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.
@ 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 or maximum on two values.
@ 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...
@ AVGFLOORS
AVGFLOORS/AVGFLOORU - Averaging add - Add two integers using an integer of type i[N+1],...
@ 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.
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.
CondCode getSetCCSwappedOperands(CondCode Operation)
Return the operation corresponding to (Y op X) when given the operation for (X op Y).
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...
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.
ID ArrayRef< Type * > Tys
Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
Libcall getSINTTOFP(EVT OpVT, EVT RetVT)
getSINTTOFP - Return the SINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
Libcall getUINTTOFP(EVT OpVT, EVT RetVT)
getUINTTOFP - Return the UINTTOFP_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
Libcall
RTLIB::Libcall enum - This enum defines all of the runtime library calls the backend can emit.
Libcall getFPTOUINT(EVT OpVT, EVT RetVT)
getFPTOUINT - Return the FPTOUINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
Libcall getFPTOSINT(EVT OpVT, EVT RetVT)
getFPTOSINT - Return the FPTOSINT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
Libcall getFPEXT(EVT OpVT, EVT RetVT)
getFPEXT - Return the FPEXT_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
Libcall getFPROUND(EVT OpVT, EVT RetVT)
getFPROUND - Return the FPROUND_*_* value for the given types, or UNKNOWN_LIBCALL if there is none.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
@ Kill
The last use of a register.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
Reg
All possible values of the reg field in the ModR/M byte.
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)
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool CC_ARM_APCS_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State)
bool RetCC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State)
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.
bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
bool isStrongerThanMonotonic(AtomicOrdering AO)
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
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...
bool FastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
bool RetCC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State)
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)
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
bool CC_ARM_AAPCS_VFP(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State)
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...
bool CC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State)
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)
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.
bool isBitwiseNot(SDValue V, bool AllowUndefs=false)
Returns true if V is a bitwise not operation.
bool RetCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State)
bool CC_ARM_Win32_CFGuard_Check(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
ComplexDeinterleavingOperation
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
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...
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
ComplexDeinterleavingRotation
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
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.
bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
bool RetFastCC_ARM_APCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State)
bool CC_ARM_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State)
DWARFExpression::Operation Op
ConstantSDNode * isConstOrConstSplat(SDValue N, bool AllowUndefs=false, bool AllowTruncation=false)
Returns the SDNode if it is a constant splat BuildVector or constant int.
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.
bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
bool isVREVMask(ArrayRef< int > M, EVT VT, unsigned BlockSize)
isVREVMask - Check if a vector shuffle corresponds to a VREV instruction with the specified blocksize...
unsigned gettBLXrOpcode(const MachineFunction &MF)
llvm::SmallVector< int, 16 > createSequentialMask(unsigned Start, unsigned NumInts, unsigned NumUndefs)
Create a sequential shuffle mask.
unsigned convertAddSubFlagsOpcode(unsigned OldOpc)
Map pseudo instructions that imply an 'S' bit onto real opcodes.
bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
static const unsigned PerfectShuffleTable[6561+1]
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...
static constexpr roundingMode rmTowardZero
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
ElementCount getVectorElementCount() const
EVT getDoubleNumVectorElementsVT(LLVMContext &Context) const
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
static EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified 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.
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.
EVT changeVectorElementType(EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
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 KnownBits mul(const KnownBits &LHS, const KnownBits &RHS, bool NoUndefSelfMultiply=false)
Compute known bits resulting from multiplying LHS and RHS.
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 MachinePointerInfo getJumpTable(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a jump table entry.
static MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
MachinePointerInfo getWithOffset(int64_t O) const
static MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static 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
CallLoweringInfo & setDiscardResult(bool Value=true)
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
void AddToWorklist(SDNode *N)
bool isCalledByLegalizer() const
bool isBeforeLegalize() const
SDValue CombineTo(SDNode *N, ArrayRef< SDValue > To, bool AddTo=true)
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...
bool CombineTo(SDValue O, SDValue N)