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()) {
1153 if (Subtarget->hasDSP()) {
1175 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6Ops()
1176 || (Subtarget->
isThumb2() && !Subtarget->hasDSP()))
1191 if (Subtarget->hasMVEIntegerOps())
1201 if (!Subtarget->
isThumb1Only() && Subtarget->hasV6T2Ops())
1212 if (!Subtarget->hasV5TOps() || Subtarget->
isThumb1Only()) {
1221 if (Subtarget->hasPerfMon())
1225 if (!Subtarget->hasV6Ops())
1228 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
1229 : Subtarget->hasDivideInARMMode();
1236 if (Subtarget->
isTargetWindows() && !Subtarget->hasDivideInThumbMode()) {
1253 HasStandaloneRem =
false;
1258 const char *
const Name;
1260 } LibraryCalls[] = {
1272 for (
const auto &LC : LibraryCalls) {
1279 const char *
const Name;
1281 } LibraryCalls[] = {
1293 for (
const auto &LC : LibraryCalls) {
1331 InsertFencesForAtomic =
false;
1333 (!Subtarget->isThumb() || Subtarget->hasV8MBaselineOps())) {
1337 if (!Subtarget->isThumb() || !Subtarget->
isMClass())
1342 if (!Subtarget->hasAcquireRelease() ||
1345 InsertFencesForAtomic =
true;
1351 if (Subtarget->hasDataBarrier())
1352 InsertFencesForAtomic =
true;
1372 if (!InsertFencesForAtomic) {
1380 (!Subtarget->
isMClass() && Subtarget->hasV6Ops())) {
1392 }
else if ((Subtarget->
isMClass() && Subtarget->hasV8MBaselineOps()) ||
1393 Subtarget->hasForced32BitAtomics()) {
1407 if (!Subtarget->hasV6Ops()) {
1413 if (!Subtarget->useSoftFloat() && Subtarget->hasFPRegs() &&
1445 if (Subtarget->hasFullFP16()) {
1455 if (Subtarget->hasFullFP16())
1470 if (!Subtarget->useSoftFloat() && Subtarget->
hasVFP2Base() &&
1484 if (!Subtarget->useSoftFloat() && !Subtarget->
isThumb1Only()) {
1492 if (!Subtarget->hasFP16()) {
1523 if (Subtarget->hasNEON()) {
1530 if (Subtarget->hasFP64()) {
1543 if (Subtarget->hasFullFP16()) {
1562 if (Subtarget->hasNEON()) {
1574 if (Subtarget->hasFullFP16()) {
1606 if (Subtarget->hasMVEIntegerOps())
1609 if (Subtarget->hasV6Ops())
1614 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) ||
1621 if (Subtarget->useSoftFloat() || Subtarget->
isThumb1Only() ||
1650 return Subtarget->useSoftFloat();
1663std::pair<const TargetRegisterClass *, uint8_t>
1674 case MVT::f32:
case MVT::f64:
case MVT::v8i8:
case MVT::v4i16:
1675 case MVT::v2i32:
case MVT::v1i64:
case MVT::v2f32:
1676 RRC = &ARM::DPRRegClass;
1684 case MVT::v16i8:
case MVT::v8i16:
case MVT::v4i32:
case MVT::v2i64:
1685 case MVT::v4f32:
case MVT::v2f64:
1686 RRC = &ARM::DPRRegClass;
1690 RRC = &ARM::DPRRegClass;
1694 RRC = &ARM::DPRRegClass;
1698 return std::make_pair(RRC,
Cost);
1702#define MAKE_CASE(V) \
1921 if ((Subtarget->hasMVEIntegerOps() &&
1922 (VT == MVT::v2i64 || VT == MVT::v4i32 || VT == MVT::v8i16 ||
1923 VT == MVT::v16i8)) ||
1924 (Subtarget->hasMVEFloatOps() &&
1925 (VT == MVT::v2f64 || VT == MVT::v4f32 || VT == MVT::v8f16)))
1939 if (Subtarget->hasNEON()) {
1940 if (VT == MVT::v4i64)
1941 return &ARM::QQPRRegClass;
1942 if (VT == MVT::v8i64)
1943 return &ARM::QQQQPRRegClass;
1945 if (Subtarget->hasMVEIntegerOps()) {
1946 if (VT == MVT::v4i64)
1947 return &ARM::MQQPRRegClass;
1948 if (VT == MVT::v8i64)
1949 return &ARM::MQQQQPRRegClass;
1958 Align &PrefAlign)
const {
1959 if (!isa<MemIntrinsic>(CI))
1977 unsigned NumVals =
N->getNumValues();
1981 for (
unsigned i = 0; i != NumVals; ++i) {
1982 EVT VT =
N->getValueType(i);
1983 if (VT == MVT::Glue || VT == MVT::Other)
1989 if (!
N->isMachineOpcode())
2013 if (
auto Const = dyn_cast<ConstantSDNode>(
Op.getOperand(1)))
2014 return Const->getZExtValue() == 16;
2021 if (
auto Const = dyn_cast<ConstantSDNode>(
Op.getOperand(1)))
2022 return Const->getZExtValue() == 16;
2029 if (
auto Const = dyn_cast<ConstantSDNode>(
Op.getOperand(1)))
2030 return Const->getZExtValue() == 16;
2099 bool isVarArg)
const {
2120 else if (Subtarget->hasFPRegs() && !Subtarget->
isThumb1Only() &&
2141 bool isVarArg)
const {
2142 return CCAssignFnForNode(
CC,
false, isVarArg);
2146 bool isVarArg)
const {
2147 return CCAssignFnForNode(
CC,
true, isVarArg);
2154 bool isVarArg)
const {
2155 switch (getEffectiveCallingConv(
CC, isVarArg)) {
2181 if (Subtarget->hasFullFP16()) {
2194 if (Subtarget->hasFullFP16()) {
2208SDValue ARMTargetLowering::LowerCallResult(
2212 SDValue ThisVal,
bool isCmseNSCall)
const {
2220 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
2225 if (i == 0 && isThisReturn) {
2227 "unexpected return calling convention register assignment");
2238 Chain =
Lo.getValue(1);
2239 InGlue =
Lo.getValue(2);
2243 Chain =
Hi.getValue(1);
2244 InGlue =
Hi.getValue(2);
2256 Chain =
Lo.getValue(1);
2257 InGlue =
Lo.getValue(2);
2260 Chain =
Hi.getValue(1);
2261 InGlue =
Hi.getValue(2);
2305std::pair<SDValue, MachinePointerInfo> ARMTargetLowering::computeAddrForCallArg(
2307 bool IsTailCall,
int SPDiff)
const {
2329 return std::make_pair(DstAddr, DstInfo);
2338ARMTargetLowering::ByValCopyKind ARMTargetLowering::ByValNeedsCopyForTailCall(
2344 if (isa<GlobalAddressSDNode>(Src) || isa<ExternalSymbolSDNode>(Src))
2349 auto *SrcFrameIdxNode = dyn_cast<FrameIndexSDNode>(Src);
2350 auto *DstFrameIdxNode = dyn_cast<FrameIndexSDNode>(Dst);
2351 if (!SrcFrameIdxNode || !DstFrameIdxNode)
2354 int SrcFI = SrcFrameIdxNode->getIndex();
2355 int DstFI = DstFrameIdxNode->getIndex();
2357 "byval passed in non-fixed stack slot");
2379 if (SrcOffset == DstOffset)
2387 RegsToPassVector &RegsToPass,
2394 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
2395 unsigned id = Subtarget->
isLittle() ? 0 : 1;
2408 std::tie(DstAddr, DstInfo) =
2409 computeAddrForCallArg(dl, DAG, NextVA, StackPtr, IsTailCall, SPDiff);
2442 bool isStructRet = (Outs.
empty()) ?
false : Outs[0].
Flags.isSRet();
2443 bool isThisReturn =
false;
2444 bool isCmseNSCall =
false;
2445 bool isSibCall =
false;
2446 bool PreferIndirect =
false;
2447 bool GuardWithBTI =
false;
2457 !Subtarget->noBTIAtReturnTwice())
2462 isCmseNSCall =
true;
2474 if (isa<GlobalAddressSDNode>(Callee)) {
2478 auto *GV = cast<GlobalAddressSDNode>(Callee)->getGlobal();
2481 PreferIndirect = Subtarget->isThumb() && Subtarget->
hasMinSize() &&
2483 return isa<Instruction>(U) &&
2484 cast<Instruction>(U)->getParent() == BB;
2491 IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
2505 "site marked musttail");
2508 unsigned NumBytes = CCInfo.getStackSize();
2517 if (isTailCall && !isSibCall) {
2524 assert(StackAlign &&
"data layout string is missing stack alignment");
2525 NumBytes =
alignTo(NumBytes, *StackAlign);
2530 SPDiff = NumReusableBytes - NumBytes;
2534 if (SPDiff < 0 && AFI->getArgRegsSaveSize() < (
unsigned)-SPDiff)
2550 RegsToPassVector RegsToPass;
2565 SDValue Src = OutVals[ArgIdx];
2568 if (!
Flags.isByVal())
2573 std::tie(Dst, DstInfo) =
2574 computeAddrForCallArg(dl, DAG, VA,
SDValue(),
true, SPDiff);
2575 ByValCopyKind
Copy = ByValNeedsCopyForTailCall(DAG, Src, Dst, Flags);
2577 if (Copy == NoCopy) {
2582 }
else if (Copy == CopyOnce) {
2586 ByValTemporaries[ArgIdx] = Src;
2588 assert(Copy == CopyViaTemp &&
"unexpected enum value");
2592 int TempFrameIdx = MFI.CreateStackObject(
2593 Flags.getByValSize(),
Flags.getNonZeroByValAlign(),
false);
2602 SDValue Ops[] = {Chain, Temp, Src, SizeNode, AlignNode};
2605 ByValTemporaries[ArgIdx] = Temp;
2608 if (!ByValCopyChains.
empty())
2618 bool AfterFormalArgLoads =
false;
2622 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
2624 ++i, ++realArgIdx) {
2626 SDValue Arg = OutVals[realArgIdx];
2628 bool isByVal =
Flags.isByVal();
2648 if (isTailCall && VA.
isMemLoc() && !AfterFormalArgLoads) {
2653 AfterFormalArgLoads =
true;
2665 auto ArgVT = Outs[realArgIdx].ArgVT;
2666 if (isCmseNSCall && (ArgVT == MVT::f16)) {
2684 PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
2685 StackPtr, MemOpChains, isTailCall, SPDiff);
2689 PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
2690 StackPtr, MemOpChains, isTailCall, SPDiff);
2695 std::tie(DstAddr, DstInfo) =
2696 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2700 PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
2701 StackPtr, MemOpChains, isTailCall, SPDiff);
2703 if (realArgIdx == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
2704 Outs[0].VT == MVT::i32) {
2706 "unexpected calling convention register assignment");
2707 assert(!
Ins.empty() && Ins[0].VT == MVT::i32 &&
2708 "unexpected use of 'returned'");
2709 isThisReturn =
true;
2714 RegsToPass.push_back(std::make_pair(VA.
getLocReg(), Arg));
2715 }
else if (isByVal) {
2717 unsigned offset = 0;
2721 unsigned ByValArgsCount = CCInfo.getInRegsParamsCount();
2722 unsigned CurByValIdx = CCInfo.getInRegsParamsProcessed();
2725 bool NeedsStackCopy;
2726 if (ByValTemporaries.
contains(realArgIdx)) {
2727 ByValSrc = ByValTemporaries[realArgIdx];
2728 NeedsStackCopy =
true;
2731 NeedsStackCopy = !isTailCall;
2735 if (CurByValIdx < ByValArgsCount) {
2736 unsigned RegBegin, RegEnd;
2737 CCInfo.getInRegsParamInfo(CurByValIdx, RegBegin, RegEnd);
2742 for (i = 0, j = RegBegin;
j < RegEnd; i++,
j++) {
2749 RegsToPass.push_back(std::make_pair(j, Load));
2754 offset = RegEnd - RegBegin;
2756 CCInfo.nextInRegsParam();
2761 if (NeedsStackCopy &&
Flags.getByValSize() > 4 * offset) {
2765 std::tie(Dst, DstInfo) =
2766 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2775 SDValue Ops[] = { Chain, Dst, Src, SizeNode, AlignNode};
2783 std::tie(DstAddr, DstInfo) =
2784 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2791 if (!MemOpChains.
empty())
2797 for (
unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
2798 Chain = DAG.
getCopyToReg(Chain, dl, RegsToPass[i].first,
2799 RegsToPass[i].second, InGlue);
2806 bool isDirect =
false;
2811 GVal =
G->getGlobal();
2812 bool isStub = !
TM.shouldAssumeDSOLocal(GVal) && Subtarget->
isTargetMachO();
2814 bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->
isMClass());
2815 bool isLocalARMFunc =
false;
2818 if (Subtarget->genLongCalls()) {
2820 "long-calls codegen is not position independent!");
2824 if (isa<GlobalAddressSDNode>(Callee)) {
2825 if (Subtarget->genExecuteOnly()) {
2844 const char *
Sym = S->getSymbol();
2846 if (Subtarget->genExecuteOnly()) {
2865 }
else if (isa<GlobalAddressSDNode>(Callee)) {
2866 if (!PreferIndirect) {
2871 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !
ARMInterworking);
2873 if (isStub && Subtarget->
isThumb1Only() && !Subtarget->hasV5TOps()) {
2885 "Windows is the only supported COFF target");
2889 else if (!
TM.shouldAssumeDSOLocal(GVal))
2905 const char *
Sym = S->getSymbol();
2906 if (isARMFunc && Subtarget->
isThumb1Only() && !Subtarget->hasV5TOps()) {
2910 ARMPCLabelIndex, 4);
2924 assert(!isARMFunc && !isDirect &&
2925 "Cannot handle call to ARM function or direct call");
2928 "call to non-secure function would "
2929 "require passing arguments on stack",
2936 "call to non-secure function would return value through pointer",
2944 if (Subtarget->isThumb()) {
2947 else if (isCmseNSCall)
2949 else if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
2954 if (!isDirect && !Subtarget->hasV5TOps())
2956 else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() &&
2969 if (isTailCall && !isSibCall) {
2974 std::vector<SDValue> Ops;
2975 Ops.push_back(Chain);
2976 Ops.push_back(Callee);
2984 for (
unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
2985 Ops.push_back(DAG.
getRegister(RegsToPass[i].first,
2986 RegsToPass[i].second.getValueType()));
2998 isThisReturn =
false;
3004 assert(Mask &&
"Missing call preserved mask for calling convention");
3008 Ops.push_back(InGlue);
3019 Chain = DAG.
getNode(CallOpc, dl, {MVT::Other, MVT::Glue}, Ops);
3031 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, dl);
3037 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
3038 InVals, isThisReturn,
3039 isThisReturn ? OutVals[0] :
SDValue(), isCmseNSCall);
3046void ARMTargetLowering::HandleByVal(
CCState *State,
unsigned &
Size,
3047 Align Alignment)
const {
3049 Alignment = std::max(Alignment,
Align(4));
3055 unsigned AlignInRegs = Alignment.
value() / 4;
3056 unsigned Waste = (ARM::R4 -
Reg) % AlignInRegs;
3057 for (
unsigned i = 0; i < Waste; ++i)
3063 unsigned Excess = 4 * (ARM::R4 -
Reg);
3070 if (NSAAOffset != 0 &&
Size > Excess) {
3082 unsigned ByValRegBegin =
Reg;
3083 unsigned ByValRegEnd = std::min<unsigned>(Reg +
Size / 4, ARM::R4);
3087 for (
unsigned i = Reg + 1; i != ByValRegEnd; ++i)
3093 Size = std::max<int>(
Size - Excess, 0);
3101bool ARMTargetLowering::IsEligibleForTailCallOptimization(
3127 if (!isa<GlobalAddressSDNode>(
Callee.getNode()) || isIndirect) {
3129 for (
Register R : {ARM::R0, ARM::R1, ARM::R2, ARM::R3})
3130 AddressRegisters.
insert(R);
3133 AddressRegisters.
insert(ARM::R12);
3136 AddressRegisters.
erase(
AL.getLocReg());
3137 if (AddressRegisters.
empty()) {
3138 LLVM_DEBUG(
dbgs() <<
"false (no reg to hold function pointer)\n");
3157 <<
" (guaranteed tail-call CC)\n");
3158 return CalleeCC == CallerCC;
3163 bool isCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
3165 if (isCalleeStructRet != isCallerStructRet) {
3181 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
3182 TT.isOSBinFormatMachO())) {
3191 getEffectiveCallingConv(CalleeCC, isVarArg),
3192 getEffectiveCallingConv(CallerCC, CallerF.
isVarArg()), MF,
C, Ins,
3200 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
3201 if (CalleeCC != CallerCC) {
3202 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
3203 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved)) {
3222 LLVM_DEBUG(
dbgs() <<
"false (parameters in CSRs do not match)\n");
3241 CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
3250 StringRef IntKind =
F.getFnAttribute(
"interrupt").getValueAsString();
3263 if (IntKind ==
"" || IntKind ==
"IRQ" || IntKind ==
"FIQ" ||
3266 else if (IntKind ==
"SWI" || IntKind ==
"UNDEF")
3270 "must be one of: IRQ, FIQ, SWI, ABORT or UNDEF");
3297 bool isLittleEndian = Subtarget->
isLittle();
3309 "secure entry function would return value through pointer",
3315 for (
unsigned i = 0, realRVLocIdx = 0;
3317 ++i, ++realRVLocIdx) {
3321 SDValue Arg = OutVals[realRVLocIdx];
3322 bool ReturnF16 =
false;
3357 auto RetVT = Outs[realRVLocIdx].ArgVT;
3379 DAG.
getVTList(MVT::i32, MVT::i32), Half);
3383 HalfGPRs.
getValue(isLittleEndian ? 0 : 1), Glue);
3389 HalfGPRs.
getValue(isLittleEndian ? 1 : 0), Glue);
3401 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
3403 fmrrd.
getValue(isLittleEndian ? 0 : 1), Glue);
3408 fmrrd.
getValue(isLittleEndian ? 1 : 0), Glue);
3452 return DAG.
getNode(RetNode, dl, MVT::Other, RetOps);
3455bool ARMTargetLowering::isUsedByReturnOnly(
SDNode *
N,
SDValue &Chain)
const {
3456 if (
N->getNumValues() != 1)
3458 if (!
N->hasNUsesOfValue(1, 0))
3466 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3468 TCChain =
Copy->getOperand(0);
3482 SDValue UseChain =
U->getOperand(0);
3490 if (
U->getOperand(
U->getNumOperands() - 1).getValueType() == MVT::Glue)
3498 if (!
Copy->hasOneUse())
3505 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3507 TCChain =
Copy->getOperand(0);
3512 bool HasRet =
false;
3527bool ARMTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
3545 &&
"LowerWRITE_REGISTER called for non-i64 type argument.");
3561 EVT PtrVT =
Op.getValueType();
3571 if (Subtarget->genExecuteOnly()) {
3573 auto T =
const_cast<Type*
>(
CP->getType());
3574 auto C =
const_cast<Constant*
>(
CP->getConstVal());
3585 return LowerGlobalAddress(GA, DAG);
3590 Align CPAlign =
CP->getAlign();
3592 CPAlign = std::max(CPAlign,
Align(4));
3593 if (
CP->isMachineConstantPoolEntry())
3605 if (Subtarget->genExecuteOnly() && !Subtarget->hasV8MBaselineOps())
3614 unsigned ARMPCLabelIndex = 0;
3617 const BlockAddress *BA = cast<BlockAddressSDNode>(
Op)->getBlockAddress();
3620 if (!IsPositionIndependent) {
3623 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
3634 if (!IsPositionIndependent)
3665ARMTargetLowering::LowerGlobalTLSAddressDarwin(
SDValue Op,
3668 "This function expects a Darwin target");
3673 SDValue DescAddr = LowerGlobalAddressDarwin(
Op, DAG);
3679 MVT::i32,
DL, Chain, DescAddr,
3703 Chain, FuncTLVGet, DAG.
getRegister(ARM::R0, MVT::i32),
3709ARMTargetLowering::LowerGlobalTLSAddressWindows(
SDValue Op,
3726 DAG.
getVTList(MVT::i32, MVT::Other), Ops);
3753 const auto *GA = cast<GlobalAddressSDNode>(
Op);
3770 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3792 Args.push_back(Entry);
3800 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3801 return CallResult.first;
3823 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3831 PtrVT, dl, Chain,
Offset,
3833 Chain =
Offset.getValue(1);
3839 PtrVT, dl, Chain,
Offset,
3849 PtrVT, dl, Chain,
Offset,
3865 return LowerGlobalTLSAddressDarwin(
Op, DAG);
3868 return LowerGlobalTLSAddressWindows(
Op, DAG);
3877 return LowerToTLSGeneralDynamicModel(GA, DAG);
3880 return LowerToTLSExecModels(GA, DAG, model);
3889 while (!Worklist.
empty()) {
3891 if (isa<ConstantExpr>(U)) {
3896 auto *
I = dyn_cast<Instruction>(U);
3897 if (!
I ||
I->getParent()->getParent() !=
F)
3925 auto *GVar = dyn_cast<GlobalVariable>(GV);
3926 if (!GVar || !GVar->hasInitializer() ||
3927 !GVar->isConstant() || !GVar->hasGlobalUnnamedAddr() ||
3928 !GVar->hasLocalLinkage())
3933 auto *
Init = GVar->getInitializer();
3935 Init->needsDynamicRelocation())
3944 auto *CDAInit = dyn_cast<ConstantDataArray>(
Init);
3947 unsigned RequiredPadding = 4 - (
Size % 4);
3948 bool PaddingPossible =
3949 RequiredPadding == 4 || (CDAInit && CDAInit->isString());
3954 unsigned PaddedSize =
Size + ((RequiredPadding == 4) ? 0 : RequiredPadding);
3978 if (RequiredPadding != 4) {
3983 while (RequiredPadding--)
3995 ++NumConstpoolPromoted;
4000 if (
const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
4001 if (!(GV = GA->getAliaseeObject()))
4003 if (
const auto *V = dyn_cast<GlobalVariable>(GV))
4004 return V->isConstant();
4005 return isa<Function>(GV);
4013 return LowerGlobalAddressWindows(
Op, DAG);
4015 return LowerGlobalAddressELF(
Op, DAG);
4017 return LowerGlobalAddressDarwin(
Op, DAG);
4025 const GlobalValue *GV = cast<GlobalAddressSDNode>(
Op)->getGlobal();
4029 if (GV->
isDSOLocal() && !Subtarget->genExecuteOnly())
4042 }
else if (Subtarget->
isROPI() && IsRO) {
4047 }
else if (Subtarget->
isRWPI() && !IsRO) {
4072 if (Subtarget->
useMovt() || Subtarget->genExecuteOnly()) {
4091 "ROPI/RWPI not currently supported for Darwin");
4094 const GlobalValue *GV = cast<GlobalAddressSDNode>(
Op)->getGlobal();
4117 "Windows on ARM expects to use movw/movt");
4119 "ROPI/RWPI not currently supported for Windows");
4122 const GlobalValue *GV = cast<GlobalAddressSDNode>(
Op)->getGlobal();
4126 else if (!
TM.shouldAssumeDSOLocal(GV))
4150 DAG.
getVTList(MVT::i32, MVT::Other),
Op.getOperand(0),
4151 Op.getOperand(1), Val);
4168SDValue ARMTargetLowering::LowerINTRINSIC_VOID(
4171 Op.getConstantOperandVal(
Op.getOperand(0).getValueType() == MVT::Other);
4175 case Intrinsic::arm_gnu_eabi_mcount: {
4184 assert(Mask &&
"Missing call preserved mask for calling convention");
4189 constexpr EVT ResultTys[] = {MVT::Other, MVT::Glue};
4193 if (Subtarget->isThumb())
4196 ARM::tBL_PUSHLR, dl, ResultTys,
4197 {ReturnAddress, DAG.getTargetConstant(ARMCC::AL, dl, PtrVT),
4198 DAG.getRegister(0, PtrVT), Callee, RegisterMask, Chain}),
4202 {ReturnAddress, Callee, RegisterMask, Chain}),
4211 unsigned IntNo =
Op.getConstantOperandVal(0);
4215 case Intrinsic::thread_pointer: {
4219 case Intrinsic::arm_cls: {
4220 const SDValue &Operand =
Op.getOperand(1);
4221 const EVT VTy =
Op.getValueType();
4232 case Intrinsic::arm_cls64: {
4235 const SDValue &Operand =
Op.getOperand(1);
4236 const EVT VTy =
Op.getValueType();
4259 case Intrinsic::eh_sjlj_lsda: {
4266 unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
4276 if (IsPositionIndependent) {
4282 case Intrinsic::arm_neon_vabs:
4285 case Intrinsic::arm_neon_vabds:
4286 if (
Op.getValueType().isInteger())
4288 Op.getOperand(1),
Op.getOperand(2));
4290 case Intrinsic::arm_neon_vabdu:
4292 Op.getOperand(1),
Op.getOperand(2));
4293 case Intrinsic::arm_neon_vmulls:
4294 case Intrinsic::arm_neon_vmullu: {
4295 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmulls)
4298 Op.getOperand(1),
Op.getOperand(2));
4300 case Intrinsic::arm_neon_vminnm:
4301 case Intrinsic::arm_neon_vmaxnm: {
4302 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminnm)
4305 Op.getOperand(1),
Op.getOperand(2));
4307 case Intrinsic::arm_neon_vminu:
4308 case Intrinsic::arm_neon_vmaxu: {
4309 if (
Op.getValueType().isFloatingPoint())
4311 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminu)
4314 Op.getOperand(1),
Op.getOperand(2));
4316 case Intrinsic::arm_neon_vmins:
4317 case Intrinsic::arm_neon_vmaxs: {
4319 if (!
Op.getValueType().isFloatingPoint()) {
4320 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
4323 Op.getOperand(1),
Op.getOperand(2));
4325 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
4328 Op.getOperand(1),
Op.getOperand(2));
4330 case Intrinsic::arm_neon_vtbl1:
4332 Op.getOperand(1),
Op.getOperand(2));
4333 case Intrinsic::arm_neon_vtbl2:
4335 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4336 case Intrinsic::arm_mve_pred_i2v:
4337 case Intrinsic::arm_mve_pred_v2i:
4340 case Intrinsic::arm_mve_vreinterpretq:
4343 case Intrinsic::arm_mve_lsll:
4345 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4346 case Intrinsic::arm_mve_asrl:
4348 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4359 if (!Subtarget->hasDataBarrier()) {
4363 assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() &&
4364 "Unexpected ISD::ATOMIC_FENCE encountered. Should be libcall!");
4375 }
else if (Subtarget->preferISHSTBarriers() &&
4384 DAG.
getConstant(Intrinsic::arm_dmb, dl, MVT::i32),
4392 (!Subtarget->
isThumb1Only() && Subtarget->hasV5TEOps())))
4394 return Op.getOperand(0);
4397 unsigned isRead =
~Op.getConstantOperandVal(2) & 1;
4399 (!Subtarget->hasV7Ops() || !Subtarget->hasMPExtension()))
4401 return Op.getOperand(0);
4403 unsigned isData =
Op.getConstantOperandVal(4);
4404 if (Subtarget->isThumb()) {
4406 isRead = ~isRead & 1;
4407 isData = ~isData & 1;
4424 const Value *SV = cast<SrcValueSDNode>(
Op.getOperand(2))->getValue();
4425 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
4433 const SDLoc &dl)
const {
4439 RC = &ARM::tGPRRegClass;
4441 RC = &ARM::GPRRegClass;
4455 MVT::i32, dl, Root, FIN,
4476 const Value *OrigArg,
4477 unsigned InRegsParamRecordIdx,
4478 int ArgOffset,
unsigned ArgSize)
const {
4493 unsigned RBegin, REnd;
4503 ArgOffset = -4 * (ARM::R4 - RBegin);
4513 for (
unsigned Reg = RBegin, i = 0;
Reg < REnd; ++
Reg, ++i) {
4522 if (!MemOps.
empty())
4531 unsigned TotalArgRegsSaveSize,
4532 bool ForceMutable)
const {
4543 CCInfo.
getStackSize(), std::max(4U, TotalArgRegsSaveSize));
4547bool ARMTargetLowering::splitValueIntoRegisterParts(
4549 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID>
CC)
const {
4551 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4563SDValue ARMTargetLowering::joinRegisterPartsIntoValue(
4565 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID>
CC)
const {
4566 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4579SDValue ARMTargetLowering::LowerFormalArguments(
4595 unsigned CurArgIdx = 0;
4607 unsigned ArgRegBegin = ARM::R4;
4614 if (!
Flags.isByVal())
4618 unsigned RBegin, REnd;
4620 ArgRegBegin = std::min(ArgRegBegin, RBegin);
4626 int lastInsIndex = -1;
4630 ArgRegBegin = std::min(ArgRegBegin, (
unsigned)
GPRArgRegs[RegIdx]);
4633 unsigned TotalArgRegsSaveSize = 4 * (ARM::R4 - ArgRegBegin);
4637 for (
unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4639 if (Ins[VA.
getValNo()].isOrigArg()) {
4640 std::advance(CurOrigArg,
4641 Ins[VA.
getValNo()].getOrigArgIndex() - CurArgIdx);
4653 GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4660 MVT::f64, dl, Chain, FIN,
4663 ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4671 ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4675 if (RegVT == MVT::f16 || RegVT == MVT::bf16)
4676 RC = &ARM::HPRRegClass;
4677 else if (RegVT == MVT::f32)
4678 RC = &ARM::SPRRegClass;
4679 else if (RegVT == MVT::f64 || RegVT == MVT::v4f16 ||
4680 RegVT == MVT::v4bf16)
4681 RC = &ARM::DPRRegClass;
4682 else if (RegVT == MVT::v2f64 || RegVT == MVT::v8f16 ||
4683 RegVT == MVT::v8bf16)
4684 RC = &ARM::QPRRegClass;
4685 else if (RegVT == MVT::i32)
4687 : &ARM::GPRRegClass;
4733 assert(VA.
getValVT() != MVT::i64 &&
"i64 should already be lowered");
4739 if (index != lastInsIndex)
4747 if (
Flags.isByVal()) {
4748 assert(Ins[index].isOrigArg() &&
4749 "Byval arguments cannot be implicit");
4753 CCInfo, DAG, dl, Chain, &*CurOrigArg, CurByValIndex,
4768 lastInsIndex = index;
4775 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.
getStackSize(),
4776 TotalArgRegsSaveSize);
4780 "secure entry function must not be variadic", dl.
getDebugLoc());
4791 assert(StackAlign &&
"data layout string is missing stack alignment");
4792 StackArgSize =
alignTo(StackArgSize, *StackAlign);
4801 "secure entry function requires arguments on stack", dl.
getDebugLoc());
4811 return CFP->getValueAPF().isPosZero();
4815 SDValue WrapperOp =
Op.getOperand(1).getOperand(0);
4817 if (
const ConstantFP *CFP = dyn_cast<ConstantFP>(CP->getConstVal()))
4818 return CFP->getValueAPF().isPosZero();
4821 Op->getValueType(0) == MVT::f64) {
4836 const SDLoc &dl)
const {
4838 unsigned C = RHSC->getZExtValue();
4904 LHS.getValueType() == MVT::i32 && isa<ConstantSDNode>(RHS) &&
4906 unsigned Mask =
LHS.getConstantOperandVal(1);
4907 auto *RHSC = cast<ConstantSDNode>(
RHS.getNode());
4908 uint64_t RHSV = RHSC->getZExtValue();
4909 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4911 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4926 isa<ConstantSDNode>(RHS) &&
RHS->getAsZExtVal() == 0x80000000U &&
4928 LHS.getConstantOperandVal(1) < 31) {
4929 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4972 bool Signaling)
const {
4973 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4988std::pair<SDValue, SDValue>
4991 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
5003 switch (
Op.getOpcode()) {
5016 DAG.
getVTList(
Op.getValueType(), MVT::i32), LHS, RHS)
5055 return std::make_pair(
Value, OverflowCmp);
5066 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
5071 EVT VT =
Op.getValueType();
5114 EVT VT =
Op.getValueType();
5118 switch (
Op.getOpcode()) {
5143 EVT VT =
Op.getValueType();
5144 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
5154 switch (
Op->getOpcode()) {
5170 switch (
Op->getOpcode()) {
5189 DAG.
getNode(NewOpcode, dl, MVT::i32,
5200 unsigned Opc =
Cond.getOpcode();
5202 if (
Cond.getResNo() == 1 &&
5210 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5211 EVT VT =
Op.getValueType();
5213 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, OverflowCmp, DAG);
5223 dyn_cast<ConstantSDNode>(
Cond.getOperand(0));
5225 dyn_cast<ConstantSDNode>(
Cond.getOperand(1));
5227 if (CMOVTrue && CMOVFalse) {
5233 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
5235 False = SelectFalse;
5236 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
5242 return getCMOV(dl,
Op.getValueType(), True, False,
Cond.getOperand(2),
5243 Cond.getOperand(3), DAG);
5258 bool &swpCmpOps,
bool &swpVselOps) {
5286 swpCmpOps = !swpCmpOps;
5287 swpVselOps = !swpVselOps;
5310 if (!Subtarget->hasFP64() && VT == MVT::f64) {
5312 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
5314 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
5349 ((K ==
LHS && K == TrueVal) || (K ==
RHS && K == FalseVal))) ||
5351 ((K ==
RHS && K == TrueVal) || (K ==
LHS && K == FalseVal)));
5372 EVT VT =
Op.getValueType();
5379 const SDValue Op2 = isa<ConstantSDNode>(TrueVal1) ? FalseVal1 : TrueVal1;
5394 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5402 if (!isa<ConstantSDNode>(K1) || !isa<ConstantSDNode>(K2))
5405 int64_t Val1 = cast<ConstantSDNode>(K1)->getSExtValue();
5406 int64_t Val2 = cast<ConstantSDNode>(K2)->getSExtValue();
5407 int64_t PosVal = std::max(Val1, Val2);
5408 int64_t NegVal = std::min(Val1, Val2);
5454 SDValue KTmp = isa<ConstantSDNode>(TrueVal) ? TrueVal : FalseVal;
5455 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5460 if (*K != KTmp || V != VTmp)
5471bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5475 return !Subtarget->hasFP64();
5477 return !Subtarget->hasFullFP16();
5482 EVT VT =
Op.getValueType();
5486 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->
isThumb2())
5498 if (VT == MVT::i32 &&
5518 if (Subtarget->hasV8_1MMainlineOps() && CFVal && CTVal &&
5519 LHS.getValueType() == MVT::i32 &&
RHS.getValueType() == MVT::i32) {
5522 unsigned Opcode = 0;
5524 if (TVal == ~FVal) {
5526 }
else if (TVal == ~FVal + 1) {
5528 }
else if (TVal + 1 == FVal) {
5530 }
else if (TVal == FVal + 1) {
5562 return DAG.
getNode(Opcode, dl, VT, TrueVal, FalseVal, ARMcc, Cmp);
5566 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5568 DAG,
LHS.getValueType(), LHS, RHS,
CC, dl, LHS, RHS);
5572 if (!
RHS.getNode()) {
5578 if (
LHS.getValueType() == MVT::i32) {
5590 TrueVal.getValueType() == MVT::f32 ||
5591 TrueVal.getValueType() == MVT::f64)) {
5605 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5617 (
TrueVal.getValueType() == MVT::f16 ||
5618 TrueVal.getValueType() == MVT::f32 ||
5619 TrueVal.getValueType() == MVT::f64)) {
5620 bool swpCmpOps =
false;
5621 bool swpVselOps =
false;
5635 SDValue Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, Cmp, DAG);
5638 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, Cmp, DAG);
5648 if (!
N->hasOneUse())
5651 if (!
N->getNumValues())
5653 EVT VT =
Op.getValueType();
5654 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5671 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5672 Ld->getPointerInfo(), Ld->getAlign(),
5673 Ld->getMemOperand()->getFlags());
5691 DAG.
getLoad(MVT::i32, dl, Ld->getChain(),
Ptr, Ld->getPointerInfo(),
5692 Ld->getAlign(), Ld->getMemOperand()->getFlags());
5694 EVT PtrType =
Ptr.getValueType();
5697 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5698 Ld->getPointerInfo().getWithOffset(4),
5700 Ld->getMemOperand()->getFlags());
5718 bool LHSSeenZero =
false;
5720 bool RHSSeenZero =
false;
5722 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5733 if (
LHS.getValueType() == MVT::f32) {
5751 SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5766 unsigned Opc =
Cond.getOpcode();
5769 if (
Cond.getResNo() == 1 &&
5779 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5802 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5804 DAG,
LHS.getValueType(), LHS, RHS,
CC, dl, LHS, RHS);
5808 if (!
RHS.getNode()) {
5816 unsigned Opc =
LHS.getOpcode();
5830 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5844 if (
LHS.getValueType() == MVT::i32) {
5853 if (
SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5884 if (Subtarget->
isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5890 Addr,
Op.getOperand(2), JTI);
5896 Chain =
Addr.getValue(1);
5903 Chain =
Addr.getValue(1);
5909 EVT VT =
Op.getValueType();
5912 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5913 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5921 const EVT OpTy =
Op.getOperand(0).getValueType();
5922 if (OpTy == MVT::v4f32)
5924 else if (OpTy == MVT::v4f16 && HasFullFP16)
5926 else if (OpTy == MVT::v8f16 && HasFullFP16)
5931 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5934 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5939 EVT VT =
Op.getValueType();
5943 bool IsStrict =
Op->isStrictFPOpcode();
5944 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5946 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5956 MakeLibCallOptions CallOptions;
5959 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5960 CallOptions, Loc, Chain);
5970 Loc,
Op.getValueType(), SrcVal);
5979 EVT VT =
Op.getValueType();
5980 EVT ToVT = cast<VTSDNode>(
Op.getOperand(1))->getVT();
5981 EVT FromVT =
Op.getOperand(0).getValueType();
5983 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5985 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5986 Subtarget->hasFP64())
5988 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5989 Subtarget->hasFullFP16())
5991 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5992 Subtarget->hasMVEFloatOps())
5994 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5995 Subtarget->hasMVEFloatOps())
5998 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
6015 EVT VT =
Op.getValueType();
6018 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
6024 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
6025 Op.getOperand(0).getValueType() == MVT::v8i16) &&
6026 "Invalid type for custom lowering!");
6031 if (VT == MVT::v4f32)
6032 DestVecType = MVT::v4i32;
6033 else if (VT == MVT::v4f16 && HasFullFP16)
6034 DestVecType = MVT::v4i16;
6035 else if (VT == MVT::v8f16 && HasFullFP16)
6036 DestVecType = MVT::v8i16;
6042 switch (
Op.getOpcode()) {
6054 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
6059 EVT VT =
Op.getValueType();
6062 if (isUnsupportedFloatingType(VT)) {
6070 MakeLibCallOptions CallOptions;
6072 CallOptions,
SDLoc(
Op)).first;
6083 EVT VT =
Op.getValueType();
6087 bool UseNEON = !InGPR && Subtarget->hasNEON();
6094 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
6101 if (SrcVT == MVT::f32) {
6107 }
else if (VT == MVT::f32)
6123 if (VT == MVT::f32) {
6135 if (SrcVT == MVT::f64)
6144 if (VT == MVT::f32) {
6168 EVT VT =
Op.getValueType();
6170 unsigned Depth =
Op.getConstantOperandVal(0);
6172 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
6191 EVT VT =
Op.getValueType();
6193 unsigned Depth =
Op.getConstantOperandVal(0);
6207 .
Case(
"sp", ARM::SP)
6222 assert(
N->getValueType(0) == MVT::i64
6223 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
6226 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
6266 const APInt &APIntIndex = Index->getAPIntValue();
6268 NewIndex *= APIntIndex;
6298 EVT SrcVT =
Op.getValueType();
6299 EVT DstVT =
N->getValueType(0);
6301 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
6302 (DstVT == MVT::f16 || DstVT == MVT::bf16))
6306 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
6307 (SrcVT == MVT::f16 || SrcVT == MVT::bf16)) {
6308 if (Subtarget->hasFullFP16() && !Subtarget->hasBF16())
6315 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
6319 if (SrcVT == MVT::i64 && TLI.
isTypeLegal(DstVT)) {
6331 if (DstVT == MVT::i64 && TLI.
isTypeLegal(SrcVT)) {
6368 EVT VT =
Op.getValueType();
6386 SDValue LoBigShift = DAG.
getNode(Opc, dl, VT, ShOpHi, ExtraShAmt);
6394 ? DAG.
getNode(Opc, dl, VT, ShOpHi,
6411 EVT VT =
Op.getValueType();
6453 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6505 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6533 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6563 EVT VT =
N->getValueType(0);
6564 if (VT.
isVector() && ST->hasNEON()) {
6573 if (ElemTy == MVT::i8) {
6581 if ((ElemTy == MVT::i16 || ElemTy == MVT::i32) &&
6596 if (ElemTy == MVT::i64) {
6609 if (!ST->hasV6T2Ops())
6618 EVT VT =
N->getValueType(0);
6621 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6622 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6623 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6624 "Unexpected type for custom ctpop lowering");
6632 unsigned EltSize = 8;
6655 Op =
Op.getOperand(0);
6657 APInt SplatBits, SplatUndef;
6658 unsigned SplatBitSize;
6661 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6663 SplatBitSize > ElementBits)
6674 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6678 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6689 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6694 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6695 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6704 EVT VT =
N->getValueType(0);
6726 "unexpected vector shift opcode");
6728 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6729 unsigned VShiftOpc =
6731 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6737 EVT ShiftVT =
N->getOperand(1).getValueType();
6740 unsigned VShiftOpc =
6742 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6747 EVT VT =
N->getValueType(0);
6756 "Unknown shift to lower!");
6758 unsigned ShOpc =
N->getOpcode();
6759 if (ST->hasMVEIntegerOps()) {
6789 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6803 if (ST->isThumb1Only())
6808 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6824 bool Invert =
false;
6831 EVT VT =
Op.getValueType();
6839 assert(ST->hasMVEIntegerOps() &&
6840 "No hardware support for integer vector comparison!");
6842 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6867 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6877 switch (SetCCOpcode) {
6881 if (ST->hasMVEFloatOps()) {
6884 Invert =
true; [[fallthrough]];
6889 case ISD::SETLT: Swap =
true; [[fallthrough]];
6893 case ISD::SETLE: Swap =
true; [[fallthrough]];
6909 Result = DAG.
getNOT(dl, Result, VT);
6912 case ISD::SETUO: Invert =
true; [[fallthrough]];
6921 Result = DAG.
getNOT(dl, Result, VT);
6927 switch (SetCCOpcode) {
6930 if (ST->hasMVEIntegerOps()) {
6933 Invert =
true; [[fallthrough]];
6936 case ISD::SETLT: Swap =
true; [[fallthrough]];
6938 case ISD::SETLE: Swap =
true; [[fallthrough]];
6947 if (ST->hasNEON() && Opc ==
ARMCC::EQ) {
6963 Result = DAG.
getNOT(dl, Result, VT);
6997 Result = DAG.
getNOT(dl, Result, VT);
7009 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
7036 unsigned OpCmode, Imm;
7047 switch (SplatBitSize) {
7052 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
7055 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
7060 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
7061 if ((SplatBits & ~0xff) == 0) {
7067 if ((SplatBits & ~0xff00) == 0) {
7070 Imm = SplatBits >> 8;
7080 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
7081 if ((SplatBits & ~0xff) == 0) {
7087 if ((SplatBits & ~0xff00) == 0) {
7090 Imm = SplatBits >> 8;
7093 if ((SplatBits & ~0xff0000) == 0) {
7096 Imm = SplatBits >> 16;
7099 if ((SplatBits & ~0xff000000) == 0) {
7102 Imm = SplatBits >> 24;
7109 if ((SplatBits & ~0xffff) == 0 &&
7110 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
7113 Imm = SplatBits >> 8;
7121 if ((SplatBits & ~0xffffff) == 0 &&
7122 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
7125 Imm = SplatBits >> 16;
7141 unsigned ImmMask = 1;
7143 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
7144 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
7146 }
else if ((SplatBits & BitMask) != 0) {
7155 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
7169 EVT VT =
Op.getValueType();
7170 bool IsDouble = (VT == MVT::f64);
7176 if (
ST->genExecuteOnly()) {
7178 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
7179 "Unexpected architecture");
7202 if (!
ST->hasVFP3Base())
7207 if (IsDouble && !Subtarget->hasFP64())
7214 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
7232 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
7241 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
7295 unsigned ExpectedElt = Imm;
7296 for (
unsigned i = 1; i < NumElts; ++i) {
7300 if (ExpectedElt == NumElts)
7303 if (M[i] < 0)
continue;
7304 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7312 bool &ReverseVEXT,
unsigned &Imm) {
7314 ReverseVEXT =
false;
7325 unsigned ExpectedElt = Imm;
7326 for (
unsigned i = 1; i < NumElts; ++i) {
7330 if (ExpectedElt == NumElts * 2) {
7335 if (M[i] < 0)
continue;
7336 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7351 return VT == MVT::v8i8 && M.size() == 8;
7356 if (Mask.size() == Elements * 2)
7357 return Index / Elements;
7358 return Mask[Index] == 0 ? 0 : 1;
7388 if (M.size() != NumElts && M.size() != NumElts*2)
7396 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7398 for (
unsigned j = 0; j < NumElts; j += 2) {
7399 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7400 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + NumElts + WhichResult))
7405 if (M.size() == NumElts*2)
7420 if (M.size() != NumElts && M.size() != NumElts*2)
7423 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7425 for (
unsigned j = 0; j < NumElts; j += 2) {
7426 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7427 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + WhichResult))
7432 if (M.size() == NumElts*2)
7452 if (M.size() != NumElts && M.size() != NumElts*2)
7455 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7457 for (
unsigned j = 0; j < NumElts; ++j) {
7458 if (M[i+j] >= 0 && (
unsigned) M[i+j] != 2 * j + WhichResult)
7463 if (M.size() == NumElts*2)
7482 if (M.size() != NumElts && M.size() != NumElts*2)
7485 unsigned Half = NumElts / 2;
7486 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7488 for (
unsigned j = 0; j < NumElts; j += Half) {
7489 unsigned Idx = WhichResult;
7490 for (
unsigned k = 0; k < Half; ++k) {
7491 int MIdx = M[i + j + k];
7492 if (MIdx >= 0 && (
unsigned) MIdx !=
Idx)
7499 if (M.size() == NumElts*2)
7523 if (M.size() != NumElts && M.size() != NumElts*2)
7526 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7528 unsigned Idx = WhichResult * NumElts / 2;
7529 for (
unsigned j = 0; j < NumElts; j += 2) {
7530 if ((M[i+j] >= 0 && (
unsigned) M[i+j] !=
Idx) ||
7531 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] !=
Idx + NumElts))
7537 if (M.size() == NumElts*2)
7556 if (M.size() != NumElts && M.size() != NumElts*2)
7559 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7561 unsigned Idx = WhichResult * NumElts / 2;
7562 for (
unsigned j = 0; j < NumElts; j += 2) {
7563 if ((M[i+j] >= 0 && (
unsigned) M[i+j] !=
Idx) ||
7564 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] !=
Idx))
7570 if (M.size() == NumElts*2)
7583 unsigned &WhichResult,
7586 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7588 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7590 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7608 if (NumElts != M.size())
7612 for (
unsigned i = 0; i != NumElts; ++i)
7613 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7622 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7630 int Ofs = Top ? 1 : 0;
7631 int Upper = SingleSource ? 0 : NumElts;
7632 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7633 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7635 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7644 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7653 unsigned Offset = Top ? 0 : 1;
7654 unsigned N = SingleSource ? 0 : NumElts;
7655 for (
unsigned i = 0; i < NumElts; i += 2) {
7656 if (M[i] >= 0 && M[i] != (
int)i)
7658 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7667 if (NumElts != M.size())
7675 unsigned Off0 = rev ? NumElts / 2 : 0;
7676 unsigned Off1 = rev ? 0 : NumElts / 2;
7677 for (
unsigned i = 0; i < NumElts; i += 2) {
7678 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7680 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7696 if (!ST->hasMVEFloatOps())
7701 if (VT != MVT::v8f16)
7722 for (
unsigned i = 1; i < 4; i++) {
7749 if (!ST->hasMVEFloatOps())
7754 if (VT != MVT::v4f32)
7770 for (
unsigned i = 1; i < 4; i++) {
7791 if (!isa<ConstantSDNode>(
N))
7793 Val =
N->getAsZExtVal();
7795 if (ST->isThumb1Only()) {
7796 if (Val <= 255 || ~Val <= 255)
7808 EVT VT =
Op.getValueType();
7810 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7814 unsigned BitsPerBool;
7818 }
else if (NumElts == 4) {
7821 }
else if (NumElts == 8) {
7824 }
else if (NumElts == 16) {
7833 if (!isa<ConstantSDNode>(FirstOp) &&
7835 return U.get().isUndef() || U.get() == FirstOp;
7843 unsigned Bits32 = 0;
7844 for (
unsigned i = 0; i < NumElts; ++i) {
7846 if (!isa<ConstantSDNode>(V) && !V.isUndef())
7848 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7850 Bits32 |= BoolMask << (i * BitsPerBool);
7856 for (
unsigned i = 0; i < NumElts; ++i) {
7858 if (isa<ConstantSDNode>(V) || V.isUndef())
7869 if (!ST->hasMVEIntegerOps())
7873 EVT VT =
Op.getValueType();
7883 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7887 for (
unsigned I = 2;
I < NumElts;
I++) {
7903 switch (
N->getOpcode()) {
7914 return N->getOperand(1).getNode() ==
Op;
7916 switch (
N->getConstantOperandVal(0)) {
7917 case Intrinsic::arm_mve_add_predicated:
7918 case Intrinsic::arm_mve_mul_predicated:
7919 case Intrinsic::arm_mve_qadd_predicated:
7920 case Intrinsic::arm_mve_vhadd:
7921 case Intrinsic::arm_mve_hadd_predicated:
7922 case Intrinsic::arm_mve_vqdmulh:
7923 case Intrinsic::arm_mve_qdmulh_predicated:
7924 case Intrinsic::arm_mve_vqrdmulh:
7925 case Intrinsic::arm_mve_qrdmulh_predicated:
7926 case Intrinsic::arm_mve_vqdmull:
7927 case Intrinsic::arm_mve_vqdmull_predicated:
7929 case Intrinsic::arm_mve_sub_predicated:
7930 case Intrinsic::arm_mve_qsub_predicated:
7931 case Intrinsic::arm_mve_vhsub:
7932 case Intrinsic::arm_mve_hsub_predicated:
7933 return N->getOperand(2).getNode() ==
Op;
7948 EVT VT =
Op.getValueType();
7956 APInt SplatBits, SplatUndef;
7957 unsigned SplatBitSize;
7959 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7966 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7968 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7969 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7970 : SplatBitSize == 16 ? MVT::v8i16
7977 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7978 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7983 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7991 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7993 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
8001 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
8011 if (
ST->hasMVEIntegerOps() &&
8012 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
8013 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
8014 : SplatBitSize == 16 ? MVT::v8i16
8031 bool isOnlyLowElement =
true;
8032 bool usesOnlyOneValue =
true;
8033 bool hasDominantValue =
false;
8040 for (
unsigned i = 0; i < NumElts; ++i) {
8045 isOnlyLowElement =
false;
8046 if (!isa<ConstantFPSDNode>(V) && !isa<ConstantSDNode>(V))
8049 unsigned &Count = ValueCounts[
V];
8052 if (++Count > (NumElts / 2)) {
8053 hasDominantValue =
true;
8057 if (ValueCounts.
size() != 1)
8058 usesOnlyOneValue =
false;
8059 if (!
Value.getNode() && !ValueCounts.
empty())
8062 if (ValueCounts.
empty())
8074 if (hasDominantValue && EltSize <= 32) {
8085 (constIndex = dyn_cast<ConstantSDNode>(
Value->getOperand(1)))) {
8090 if (VT !=
Value->getOperand(0).getValueType()) {
8103 if (!usesOnlyOneValue) {
8106 for (
unsigned I = 0;
I < NumElts; ++
I) {
8121 assert(FVT == MVT::f32 || FVT == MVT::f16);
8122 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
8123 for (
unsigned i = 0; i < NumElts; ++i)
8128 Val = LowerBUILD_VECTOR(Val, DAG, ST);
8132 if (usesOnlyOneValue) {
8159 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
8179 if (EltSize >= 32) {
8185 for (
unsigned i = 0; i < NumElts; ++i)
8199 for (
unsigned i = 0 ; i < NumElts; ++i) {
8218 EVT VT =
Op.getValueType();
8221 struct ShuffleSourceInfo {
8223 unsigned MinElt = std::numeric_limits<unsigned>::max();
8224 unsigned MaxElt = 0;
8234 int WindowScale = 1;
8236 ShuffleSourceInfo(
SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
8238 bool operator ==(
SDValue OtherVec) {
return Vec == OtherVec; }
8244 for (
unsigned i = 0; i < NumElts; ++i) {
8252 }
else if (!isa<ConstantSDNode>(
V.getOperand(1))) {
8259 SDValue SourceVec =
V.getOperand(0);
8261 if (Source == Sources.
end())
8265 unsigned EltNo =
V.getConstantOperandVal(1);
8272 if (Sources.
size() > 2)
8278 for (
auto &Source : Sources) {
8279 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
8280 if (SrcEltTy.
bitsLT(SmallestEltTy))
8281 SmallestEltTy = SrcEltTy;
8283 unsigned ResMultiplier =
8291 for (
auto &Src : Sources) {
8292 EVT SrcVT = Src.ShuffleVec.getValueType();
8296 if (SrcVTSize == VTSize)
8305 if (SrcVTSize < VTSize) {
8306 if (2 * SrcVTSize != VTSize)
8312 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
8316 if (SrcVTSize != 2 * VTSize)
8319 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
8324 if (Src.MinElt >= NumSrcElts) {
8329 Src.WindowBase = -NumSrcElts;
8330 }
else if (Src.MaxElt < NumSrcElts) {
8347 Src.WindowBase = -Src.MinElt;
8354 for (
auto &Src : Sources) {
8355 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
8356 if (SrcEltTy == SmallestEltTy)
8361 Src.WindowBase *= Src.WindowScale;
8366 for (
auto Src : Sources)
8367 assert(Src.ShuffleVec.getValueType() == ShuffleVT);
8375 if (
Entry.isUndef())
8379 int EltNo = cast<ConstantSDNode>(
Entry.getOperand(1))->getSExtValue();
8384 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
8387 int LanesDefined = BitsDefined / BitsPerShuffleLane;
8391 int *LaneMask = &
Mask[i * ResMultiplier];
8393 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
8394 ExtractBase += NumElts * (Src - Sources.begin());
8395 for (
int j = 0;
j < LanesDefined; ++
j)
8396 LaneMask[j] = ExtractBase + j;
8402 assert(Sources.size() <= 2 &&
"Too many sources!");
8405 for (
unsigned i = 0; i < Sources.size(); ++i)
8434 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8454 unsigned PFIndexes[4];
8455 for (
unsigned i = 0; i != 4; ++i) {
8459 PFIndexes[i] = M[i];
8463 unsigned PFTableIndex =
8464 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8466 unsigned Cost = (PFEntry >> 30);
8472 bool ReverseVEXT, isV_UNDEF;
8473 unsigned Imm, WhichResult;
8476 if (EltSize >= 32 ||
8483 else if (Subtarget->hasNEON() &&
8488 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8491 else if (Subtarget->hasMVEIntegerOps() &&
8495 else if (Subtarget->hasMVEIntegerOps() &&
8509 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8510 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8511 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8514 if (LHSID == (1*9+2)*9+3)
return LHS;
8515 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8572 for (
int I : ShuffleMask)
8575 if (V2.getNode()->isUndef())
8585 EVT VT =
Op.getValueType();
8587 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8588 "Expect an v8i16/v16i8 type");
8594 std::vector<int> NewMask;
8598 NewMask.push_back(i);
8638 if (VT != MVT::v16i1)
8654 EVT VT =
Op.getValueType();
8658 assert(ST->hasMVEIntegerOps() &&
8659 "No support for vector shuffle of boolean predicates");
8685 "Expected identical vector type in expanded i1 shuffle!");
8689 PredAsVector2, ShuffleMask);
8694 if (VT == MVT::v2i1) {
8711 EVT VT =
Op.getValueType();
8715 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8716 "Unexpected vector type");
8718 int QuarterSize = NumElts / 4;
8727 for (
int i = 0; i <
Length; i++) {
8728 if (ShuffleMask[Start + i] >= 0) {
8729 if (ShuffleMask[Start + i] %
Length != i)
8731 MovIdx = ShuffleMask[Start + i] /
Length;
8739 for (
int i = 1; i <
Length; i++) {
8740 if (ShuffleMask[Start + i] >= 0 &&
8741 (ShuffleMask[Start + i] /
Length != MovIdx ||
8742 ShuffleMask[Start + i] %
Length != i))
8748 for (
int Part = 0; Part < 4; ++Part) {
8750 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8754 Input =
Op->getOperand(1);
8764 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8769 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8771 for (
int Part = 0; Part < 4; ++Part)
8772 for (
int i = 0; i < QuarterSize; i++)
8774 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8776 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8779 for (
int Part = 0; Part < 4; ++Part)
8795 EVT VT =
Op.getValueType();
8807 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8811 if (Mask[i] != i + BaseOffset) {
8812 if (OffElement == -1)
8818 return NonUndef > 2 && OffElement != -1;
8822 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8824 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8835 ShuffleMask[OffElement] < (
int)NumElts ? V1 : V2,
8846 EVT VT =
Op.getValueType();
8850 if (ST->hasMVEIntegerOps() && EltSize == 1)
8861 if (EltSize <= 32) {
8865 if (Lane == -1) Lane = 0;
8876 bool IsScalarToVector =
true;
8879 IsScalarToVector =
false;
8882 if (IsScalarToVector)
8889 bool ReverseVEXT =
false;
8891 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) {
8915 unsigned WhichResult = 0;
8916 bool isV_UNDEF =
false;
8917 if (ST->hasNEON()) {
8919 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8926 if (ST->hasMVEIntegerOps()) {
8961 }) &&
"Unexpected shuffle index into UNDEF operand!");
8964 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8967 assert((WhichResult == 0) &&
8968 "In-place shuffle of concat can only have one result!");
8977 if (ST->hasMVEIntegerOps() && EltSize <= 32) {
8981 for (
bool Top : {
false,
true}) {
8982 for (
bool SingleSource : {
false,
true}) {
8983 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8988 SingleSource ? V1 : V2);
9004 unsigned PFIndexes[4];
9005 for (
unsigned i = 0; i != 4; ++i) {
9006 if (ShuffleMask[i] < 0)
9009 PFIndexes[i] = ShuffleMask[i];
9013 unsigned PFTableIndex =
9014 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
9016 unsigned Cost = (PFEntry >> 30);
9022 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
9023 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
9033 if (EltSize >= 32) {
9041 for (
unsigned i = 0; i < NumElts; ++i) {
9042 if (ShuffleMask[i] < 0)
9046 ShuffleMask[i] < (
int)NumElts ? V1 : V2,
9054 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
9058 if (ST->hasNEON() && VT == MVT::v8i8)
9062 if (ST->hasMVEIntegerOps())
9071 EVT VecVT =
Op.getOperand(0).getValueType();
9074 assert(ST->hasMVEIntegerOps() &&
9075 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
9079 unsigned Lane =
Op.getConstantOperandVal(2);
9080 unsigned LaneWidth =
9082 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
9094 if (!isa<ConstantSDNode>(Lane))
9100 if (Subtarget->hasMVEIntegerOps() &&
9101 Op.getValueType().getScalarSizeInBits() == 1)
9125 IVecIn, IElt, Lane);
9134 EVT VecVT =
Op.getOperand(0).getValueType();
9137 assert(ST->hasMVEIntegerOps() &&
9138 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
9142 unsigned Lane =
Op.getConstantOperandVal(1);
9143 unsigned LaneWidth =
9154 if (!isa<ConstantSDNode>(Lane))
9174 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
9175 "Unexpected custom CONCAT_VECTORS lowering");
9177 "Unexpected custom CONCAT_VECTORS lowering");
9178 assert(ST->hasMVEIntegerOps() &&
9179 "CONCAT_VECTORS lowering only supported for MVE");
9183 EVT Op2VT = V2.getValueType();
9184 assert(Op1VT == Op2VT &&
"Operand types don't match!");
9185 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
9186 "Unexpected i1 concat operations!");
9199 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
9213 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
9214 EVT NewVT = NewV.getValueType();
9215 EVT ConcatVT = ConVec.getValueType();
9216 unsigned ExtScale = 1;
9217 if (NewVT == MVT::v2f64) {
9231 ConVec = ExtractInto(NewV1, ConVec, j);
9232 ConVec = ExtractInto(NewV2, ConVec, j);
9242 while (ConcatOps.
size() > 1) {
9243 for (
unsigned I = 0, E = ConcatOps.
size();
I != E;
I += 2) {
9246 ConcatOps[
I / 2] = ConcatPair(V1, V2);
9250 return ConcatOps[0];
9255 EVT VT =
Op->getValueType(0);
9262 "unexpected CONCAT_VECTORS");
9283 EVT VT =
Op.getValueType();
9286 unsigned Index = V2->getAsZExtVal();
9289 "Unexpected custom EXTRACT_SUBVECTOR lowering");
9290 assert(ST->hasMVEIntegerOps() &&
9291 "EXTRACT_SUBVECTOR lowering only supported for MVE");
9301 EVT SubVT = MVT::v4i32;
9303 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j += 2) {
9318 for (
unsigned i = Index, j = 0; i < (Index + NumElts); i++, j++) {
9334 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
9335 EVT VT =
N->getValueType(0);
9336 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
9337 "Expected a vector i1 type!");
9339 EVT FromVT =
Op.getValueType();
9350 if (!Subtarget->hasMVEIntegerOps())
9353 EVT ToVT =
N->getValueType(0);
9396 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
9398 EVT FromVT =
N->getOperand(0).getValueType();
9399 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9410 if (!Subtarget->hasMVEIntegerOps())
9415 EVT ToVT =
N->getValueType(0);
9416 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9419 EVT FromVT =
Op.getValueType();
9420 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9431 SDValue Ext1 = Ext.getValue(1);
9434 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9435 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9447 EVT VT =
N->getValueType(0);
9449 SDNode *BVN =
N->getOperand(0).getNode();
9454 unsigned HiElt = 1 - LoElt;
9459 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9475 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9476 SDNode *Elt =
N->getOperand(i).getNode();
9479 unsigned HalfSize = EltSize / 2;
9481 if (!
isIntN(HalfSize,
C->getSExtValue()))
9484 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9523 switch (OrigSimpleTy) {
9539 unsigned ExtOpcode) {
9562 if (ExtendedTy == LD->getMemoryVT())
9563 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9564 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9565 LD->getMemOperand()->getFlags());
9571 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9572 LD->getMemoryVT(), LD->getAlign(),
9573 LD->getMemOperand()->getFlags());
9586 N->getOperand(0)->getValueType(0),
9592 "Expected extending load");
9598 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9607 SDNode *BVN =
N->getOperand(0).getNode();
9609 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9617 EVT VT =
N->getValueType(0);
9623 for (
unsigned i = 0; i != NumElts; ++i) {
9624 const APInt &CInt =
N->getConstantOperandAPInt(i);
9633 unsigned Opcode =
N->getOpcode();
9635 SDNode *N0 =
N->getOperand(0).getNode();
9636 SDNode *N1 =
N->getOperand(1).getNode();
9644 unsigned Opcode =
N->getOpcode();
9646 SDNode *N0 =
N->getOperand(0).getNode();
9647 SDNode *N1 =
N->getOperand(1).getNode();
9657 EVT VT =
Op.getValueType();
9659 "unexpected type for custom-lowering ISD::MUL");
9660 SDNode *N0 =
Op.getOperand(0).getNode();
9661 SDNode *N1 =
Op.getOperand(1).getNode();
9662 unsigned NewOpc = 0;
9666 if (isN0SExt && isN1SExt)
9671 if (isN0ZExt && isN1ZExt)
9673 else if (isN1SExt || isN1ZExt) {
9690 if (VT == MVT::v2i64)
9707 "unexpected types for extended operands to VMULL");
9708 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9743 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9777 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9780 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9801 EVT VT =
Op.getValueType();
9802 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9803 "unexpected type for custom-lowering ISD::SDIV");
9810 if (VT == MVT::v8i8) {
9838 EVT VT =
Op.getValueType();
9839 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9840 "unexpected type for custom-lowering ISD::UDIV");
9847 if (VT == MVT::v8i8) {
9886 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9889 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9893 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9914 EVT VT =
N->getValueType(0);
9928 Op.getOperand(1), Carry);
9942 Op.getOperand(1), Carry);
9975 bool ShouldUseSRet = Subtarget->
isAPCS_ABI();
9977 if (ShouldUseSRet) {
9987 Entry.IsSExt =
false;
9988 Entry.IsZExt =
false;
9989 Entry.IsSRet =
true;
9990 Args.push_back(Entry);
9997 Entry.IsSExt =
false;
9998 Entry.IsZExt =
false;
9999 Args.push_back(Entry);
10002 (ArgVT == MVT::f64) ? RTLIB::SINCOS_STRET_F64 : RTLIB::SINCOS_STRET_F32;
10012 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
10014 if (!ShouldUseSRet)
10015 return CallResult.first;
10034 EVT VT =
Op.getValueType();
10035 assert((VT == MVT::i32 || VT == MVT::i64) &&
10036 "unexpected type for custom lowering DIV");
10042 const char *
Name =
nullptr;
10044 Name = (VT == MVT::i32) ?
"__rt_sdiv" :
"__rt_sdiv64";
10046 Name = (VT == MVT::i32) ?
"__rt_udiv" :
"__rt_udiv64";
10052 for (
auto AI : {1, 0}) {
10054 Arg.Node =
Op.getOperand(AI);
10055 Arg.Ty = Arg.Node.getValueType().getTypeForEVT(*DAG.
getContext());
10056 Args.push_back(Arg);
10059 CallLoweringInfo CLI(DAG);
10063 ES, std::move(Args));
10073ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
10081 const bool MinSize =
ST.hasMinSize();
10082 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
10083 :
ST.hasDivideInARMMode();
10087 if (
N->getOperand(0).getValueType().isVector())
10092 if (!(MinSize && HasDivide))
10105 if (Divisor.
sgt(128))
10113 assert(
Op.getValueType() == MVT::i32 &&
10114 "unexpected type for custom lowering DIV");
10120 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
10126 if (
N->getValueType(0) == MVT::i32)
10134void ARMTargetLowering::ExpandDIV_Windows(
10140 assert(
Op.getValueType() == MVT::i64 &&
10141 "unexpected type for custom lowering DIV");
10158 EVT MemVT = LD->getMemoryVT();
10159 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10160 MemVT == MVT::v16i1) &&
10161 "Expected a predicate type!");
10162 assert(MemVT ==
Op.getValueType());
10164 "Expected a non-extending load");
10165 assert(LD->isUnindexed() &&
"Expected a unindexed load");
10179 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
10181 LD->getMemOperand());
10188 if (MemVT != MVT::v16i1)
10197 EVT MemVT =
LD->getMemoryVT();
10198 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
10200 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10206 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
10216 EVT MemVT = ST->getMemoryVT();
10217 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10218 MemVT == MVT::v16i1) &&
10219 "Expected a predicate type!");
10220 assert(MemVT == ST->getValue().getValueType());
10221 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
10222 assert(ST->isUnindexed() &&
"Expected a unindexed store");
10227 SDValue Build = ST->getValue();
10228 if (MemVT != MVT::v16i1) {
10247 ST->getChain(), dl, GRP, ST->getBasePtr(),
10249 ST->getMemOperand());
10255 EVT MemVT = ST->getMemoryVT();
10256 assert(ST->isUnindexed() &&
"Stores should be unindexed at this point.");
10258 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10274 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
10275 MemVT, ST->getMemOperand());
10276 }
else if (Subtarget->hasMVEIntegerOps() &&
10277 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10278 MemVT == MVT::v16i1))) {
10293 MVT VT =
Op.getSimpleValueType();
10295 SDValue PassThru =
N->getPassThru();
10306 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
10307 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
10308 N->getExtensionType(),
N->isExpandingLoad());
10313 if (!PassThru.
isUndef() && !PassThruIsCastZero)
10320 if (!ST->hasMVEIntegerOps())
10324 unsigned BaseOpcode = 0;
10325 switch (
Op->getOpcode()) {
10341 unsigned NumActiveLanes = NumElts;
10343 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10344 NumActiveLanes == 2) &&
10345 "Only expected a power 2 vector size");
10349 while (NumActiveLanes > 4) {
10352 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
10353 NumActiveLanes /= 2;
10357 if (NumActiveLanes == 4) {
10367 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10368 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
10369 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
10375 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10379 if (EltVT !=
Op->getValueType(0))
10386 if (!ST->hasMVEFloatOps())
10393 if (!ST->hasNEON())
10401 unsigned PairwiseIntrinsic = 0;
10402 switch (
Op->getOpcode()) {
10406 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
10409 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
10412 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
10415 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
10421 unsigned NumActiveLanes = NumElts;
10423 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10424 NumActiveLanes == 2) &&
10425 "Only expected a power 2 vector size");
10431 VT =
Lo.getValueType();
10433 NumActiveLanes /= 2;
10437 while (NumActiveLanes > 1) {
10439 NumActiveLanes /= 2;
10446 if (EltVT !=
Op.getValueType()) {
10447 unsigned Extend = 0;
10448 switch (
Op->getOpcode()) {
10460 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10482 SDValue Ops[] = {
N->getOperand(0),
10492 DAG.
getVTList(MVT::i32, MVT::Other), Ops);
10505 const SDValue Ops[] = {RegClass, V0, SubReg0, V1, SubReg1};
10507 DAG.
getMachineNode(TargetOpcode::REG_SEQUENCE, dl, MVT::Untyped, Ops), 0);
10511 SDLoc dl(V.getNode());
10512 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10522 assert(
N->getValueType(0) == MVT::i64 &&
10523 "AtomicCmpSwap on types less than 64 should be legal");
10532 ARM::CMP_SWAP_64,
SDLoc(
N),
10533 DAG.
getVTList(MVT::Untyped, MVT::Untyped, MVT::Other), Ops);
10552 EVT VT =
Op.getValueType();
10561 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10563 DAG,
LHS.getValueType(), LHS, RHS,
CC, dl, LHS, RHS, Chain, IsSignaling);
10564 if (!
RHS.getNode()) {
10579 SDValue Cmp = getVFPCmp(LHS, RHS, DAG, dl, IsSignaling);
10580 SDValue Result = getCMOV(dl, VT, False, True, ARMcc, Cmp, DAG);
10582 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10583 Result = getCMOV(dl, VT, Result, True, ARMcc, Cmp, DAG);
10600 MakeLibCallOptions CallOptions;
10601 MVT SVT =
Op.getOperand(0).getSimpleValueType();
10604 makeLibCall(DAG, LC, MVT::f32,
Op.getOperand(0), CallOptions,
DL).first;
10610 switch (
Op.getOpcode()) {
10642 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10646 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10647 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10669 return LowerSET_FPMODE(
Op, DAG);
10671 return LowerRESET_FPMODE(
Op, DAG);
10675 return LowerDIV_Windows(
Op, DAG,
true);
10679 return LowerDIV_Windows(
Op, DAG,
false);
10686 return LowerSignedALUO(
Op, DAG);
10689 return LowerUnsignedALUO(
Op, DAG);
10723 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10732 return LowerSPONENTRY(
Op, DAG);
10734 return LowerFP_TO_BF16(
Op, DAG);
10741 unsigned IntNo =
N->getConstantOperandVal(0);
10743 if (IntNo == Intrinsic::arm_smlald)
10745 else if (IntNo == Intrinsic::arm_smlaldx)
10747 else if (IntNo == Intrinsic::arm_smlsld)
10749 else if (IntNo == Intrinsic::arm_smlsldx)
10756 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(3), dl, MVT::i32, MVT::i32);
10760 N->getOperand(1),
N->getOperand(2),
10772 switch (
N->getOpcode()) {
10779 Res = ExpandBITCAST(
N, DAG, Subtarget);
10788 Res = LowerREM(
N, DAG);
10792 Res = LowerDivRem(
SDValue(
N, 0), DAG);
10846 "ROPI/RWPI not currently supported with SjLj");
10855 bool isThumb = Subtarget->isThumb();
10856 bool isThumb2 = Subtarget->
isThumb2();
10859 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10865 : &ARM::GPRRegClass;
10883 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10889 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10895 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10913 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10918 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10923 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10928 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10934 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
10949 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10955 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10979 : &ARM::GPRnopcRegClass;
10984 unsigned MaxCSNum = 0;
10992 if (!
II.isEHLabel())
10996 if (!MF->hasCallSiteLandingPad(
Sym))
continue;
10999 for (
unsigned Idx : CallSiteIdxs) {
11000 CallSiteNumToLPad[
Idx].push_back(&BB);
11001 MaxCSNum = std::max(MaxCSNum,
Idx);
11008 std::vector<MachineBasicBlock*> LPadList;
11011 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
11014 LPadList.push_back(
MBB);
11019 assert(!LPadList.empty() &&
11020 "No landing pad destinations for the dispatch jump table!");
11034 unsigned trap_opcode;
11035 if (Subtarget->isThumb())
11036 trap_opcode = ARM::tTRAP;
11038 trap_opcode = Subtarget->useNaClTrap() ? ARM::TRAPNaCl : ARM::TRAP;
11047 MF->insert(MF->end(), DispatchBB);
11048 MF->insert(MF->end(), DispContBB);
11049 MF->insert(MF->end(), TrapBB);
11053 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
11060 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
11072 unsigned NumLPads = LPadList.size();
11074 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11075 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
11081 if (NumLPads < 256) {
11082 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
11084 .
addImm(LPadList.size())
11087 Register VReg1 =
MRI->createVirtualRegister(TRC);
11088 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
11089 .
addImm(NumLPads & 0xFFFF)
11092 unsigned VReg2 = VReg1;
11093 if ((NumLPads & 0xFFFF0000) != 0) {
11094 VReg2 =
MRI->createVirtualRegister(TRC);
11095 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
11101 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
11107 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
11112 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11113 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
11117 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11118 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
11125 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
11129 }
else if (Subtarget->isThumb()) {
11130 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11131 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
11137 if (NumLPads < 256) {
11138 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
11145 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
11148 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
11151 Register VReg1 =
MRI->createVirtualRegister(TRC);
11152 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
11156 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
11162 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
11167 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
11168 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
11174 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11175 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
11179 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11180 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
11190 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
11191 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
11197 unsigned NewVReg6 = NewVReg5;
11198 if (IsPositionIndependent) {
11199 NewVReg6 =
MRI->createVirtualRegister(TRC);
11200 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
11207 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
11211 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11212 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
11218 if (NumLPads < 256) {
11219 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
11223 }
else if (Subtarget->hasV6T2Ops() && isUInt<16>(NumLPads)) {
11224 Register VReg1 =
MRI->createVirtualRegister(TRC);
11225 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
11226 .
addImm(NumLPads & 0xFFFF)
11229 unsigned VReg2 = VReg1;
11230 if ((NumLPads & 0xFFFF0000) != 0) {
11231 VReg2 =
MRI->createVirtualRegister(TRC);
11232 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
11238 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11245 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
11248 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
11251 Register VReg1 =
MRI->createVirtualRegister(TRC);
11252 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
11257 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11268 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11269 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
11274 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11275 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
11282 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
11283 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
11290 if (IsPositionIndependent) {
11291 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11296 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11305 if (SeenMBBs.
insert(CurMBB).second)
11317 while (!Successors.empty()) {
11326 BB->normalizeSuccProbs();
11333 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11334 if (!
II->isCall())
continue;
11338 OI =
II->operands_begin(), OE =
II->operands_end();
11340 if (!OI->isReg())
continue;
11341 DefRegs[OI->getReg()] =
true;
11346 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11347 unsigned Reg = SavedRegs[i];
11349 !ARM::tGPRRegClass.contains(Reg) &&
11350 !ARM::hGPRRegClass.contains(Reg))
11352 if (Subtarget->
isThumb1Only() && !ARM::tGPRRegClass.contains(Reg))
11354 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(Reg))
11367 MBBLPad->setIsEHPad(
false);
11370 MI.eraseFromParent();
11383static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11385 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11386 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11388 return LdSize == 4 ? ARM::tLDRi
11389 : LdSize == 2 ? ARM::tLDRHi
11390 : LdSize == 1 ? ARM::tLDRBi : 0;
11392 return LdSize == 4 ? ARM::t2LDR_POST
11393 : LdSize == 2 ? ARM::t2LDRH_POST
11394 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11395 return LdSize == 4 ? ARM::LDR_POST_IMM
11396 : LdSize == 2 ? ARM::LDRH_POST
11397 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11402static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11404 return StSize == 16 ? ARM::VST1q32wb_fixed
11405 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11407 return StSize == 4 ? ARM::tSTRi
11408 : StSize == 2 ? ARM::tSTRHi
11409 : StSize == 1 ? ARM::tSTRBi : 0;
11411 return StSize == 4 ? ARM::t2STR_POST
11412 : StSize == 2 ? ARM::t2STRH_POST
11413 : StSize == 1 ? ARM::t2STRB_POST : 0;
11414 return StSize == 4 ? ARM::STR_POST_IMM
11415 : StSize == 2 ? ARM::STRH_POST
11416 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11423 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11424 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11425 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11426 assert(LdOpc != 0 &&
"Should have a load opcode");
11433 }
else if (IsThumb1) {
11439 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11444 }
else if (IsThumb2) {
11464 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11465 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11466 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11467 assert(StOpc != 0 &&
"Should have a store opcode");
11469 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11474 }
else if (IsThumb1) {
11481 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11486 }
else if (IsThumb2) {
11487 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11493 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11514 unsigned SizeVal =
MI.getOperand(2).getImm();
11515 unsigned Alignment =
MI.getOperand(3).getImm();
11520 unsigned UnitSize = 0;
11525 bool IsThumb2 = Subtarget->
isThumb2();
11526 bool IsThumb = Subtarget->isThumb();
11528 if (Alignment & 1) {
11530 }
else if (Alignment & 2) {
11535 Subtarget->hasNEON()) {
11536 if ((Alignment % 16 == 0) && SizeVal >= 16)
11538 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11547 bool IsNeon = UnitSize >= 8;
11548 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11550 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11551 : UnitSize == 8 ? &ARM::DPRRegClass
11554 unsigned BytesLeft = SizeVal % UnitSize;
11555 unsigned LoopSize = SizeVal - BytesLeft;
11557 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11561 unsigned srcIn = src;
11562 unsigned destIn = dest;
11563 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11564 Register srcOut =
MRI.createVirtualRegister(TRC);
11565 Register destOut =
MRI.createVirtualRegister(TRC);
11566 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11568 IsThumb1, IsThumb2);
11570 IsThumb1, IsThumb2);
11578 for (
unsigned i = 0; i < BytesLeft; i++) {
11579 Register srcOut =
MRI.createVirtualRegister(TRC);
11580 Register destOut =
MRI.createVirtualRegister(TRC);
11581 Register scratch =
MRI.createVirtualRegister(TRC);
11583 IsThumb1, IsThumb2);
11585 IsThumb1, IsThumb2);
11589 MI.eraseFromParent();
11615 MF->
insert(It, loopMBB);
11616 MF->
insert(It, exitMBB);
11619 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11629 Register varEnd =
MRI.createVirtualRegister(TRC);
11631 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11634 }
else if (Subtarget->genExecuteOnly()) {
11635 assert(IsThumb &&
"Non-thumb expected to have used movt");
11640 const Constant *
C = ConstantInt::get(Int32Ty, LoopSize);
11671 Register varLoop =
MRI.createVirtualRegister(TRC);
11672 Register varPhi =
MRI.createVirtualRegister(TRC);
11673 Register srcLoop =
MRI.createVirtualRegister(TRC);
11674 Register srcPhi =
MRI.createVirtualRegister(TRC);
11675 Register destLoop =
MRI.createVirtualRegister(TRC);
11676 Register destPhi =
MRI.createVirtualRegister(TRC);
11684 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11690 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11692 IsThumb1, IsThumb2);
11694 IsThumb1, IsThumb2);
11698 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11706 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11715 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11724 auto StartOfExit = exitMBB->
begin();
11728 unsigned srcIn = srcLoop;
11729 unsigned destIn = destLoop;
11730 for (
unsigned i = 0; i < BytesLeft; i++) {
11731 Register srcOut =
MRI.createVirtualRegister(TRC);
11732 Register destOut =
MRI.createVirtualRegister(TRC);
11733 Register scratch =
MRI.createVirtualRegister(TRC);
11734 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11735 IsThumb1, IsThumb2);
11736 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11737 IsThumb1, IsThumb2);
11742 MI.eraseFromParent();
11754 "__chkstk is only supported on Windows");
11755 assert(Subtarget->
isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11775 switch (
TM.getCodeModel()) {
11817 MI.eraseFromParent();
11841 .
addReg(
MI.getOperand(0).getReg())
11849 MI.eraseFromParent();
11873 if (miI == BB->
end()) {
11875 if (Succ->isLiveIn(ARM::CPSR))
11881 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11893 Register AddDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11894 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11900 Register LsrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11901 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11907 Register TotalIterationsReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11908 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11911 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11912 .
addUse(TotalIterationsReg)
11919 return TotalIterationsReg;
11930 Register TotalIterationsReg,
bool IsMemcpy) {
11937 SrcPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11938 CurrSrcReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11939 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11947 Register DestPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11948 Register CurrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11949 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11956 Register LoopCounterPhiReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11957 Register RemainingLoopIterationsReg =
11958 MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11959 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11960 .
addUse(TotalIterationsReg)
11962 .
addUse(RemainingLoopIterationsReg)
11966 Register PredCounterPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11967 Register RemainingElementsReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11968 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11969 .
addUse(ElementCountReg)
11971 .
addUse(RemainingElementsReg)
11975 Register VccrReg =
MRI.createVirtualRegister(&ARM::VCCRRegClass);
11976 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11977 .
addUse(PredCounterPhiReg)
11982 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11983 .
addUse(PredCounterPhiReg)
11991 SrcValueReg =
MRI.createVirtualRegister(&ARM::MQPRRegClass);
11992 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
12001 SrcValueReg = OpSrcReg;
12003 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
12014 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
12015 .
addUse(LoopCounterPhiReg)
12018 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
12019 .
addUse(RemainingLoopIterationsReg)
12032 bool isThumb2 = Subtarget->
isThumb2();
12033 switch (
MI.getOpcode()) {
12040 case ARM::tLDR_postidx: {
12044 .
add(
MI.getOperand(2))
12045 .
add(
MI.getOperand(3))
12046 .
add(
MI.getOperand(4))
12047 .
add(
MI.getOperand(0))
12049 MI.eraseFromParent();
12053 case ARM::MVE_MEMCPYLOOPINST:
12054 case ARM::MVE_MEMSETLOOPINST: {
12084 Register OpDestReg =
MI.getOperand(0).getReg();
12085 Register OpSrcReg =
MI.getOperand(1).getReg();
12086 Register OpSizeReg =
MI.getOperand(2).getReg();
12106 if (TpExit == BB) {
12108 "block containing memcpy/memset Pseudo");
12121 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
12123 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
12138 MI.eraseFromParent();
12148 case ARM::t2STR_preidx:
12149 MI.setDesc(
TII->get(ARM::t2STR_PRE));
12151 case ARM::t2STRB_preidx:
12152 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
12154 case ARM::t2STRH_preidx:
12155 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
12158 case ARM::STRi_preidx:
12159 case ARM::STRBi_preidx: {
12160 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
12161 : ARM::STRB_PRE_IMM;
12163 unsigned Offset =
MI.getOperand(4).getImm();
12171 .
add(
MI.getOperand(0))
12172 .
add(
MI.getOperand(1))
12173 .
add(
MI.getOperand(2))
12175 .
add(
MI.getOperand(5))
12176 .
add(
MI.getOperand(6))
12178 MI.eraseFromParent();
12181 case ARM::STRr_preidx:
12182 case ARM::STRBr_preidx:
12183 case ARM::STRH_preidx: {
12185 switch (
MI.getOpcode()) {
12187 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
12188 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
12189 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
12194 MI.eraseFromParent();
12198 case ARM::tMOVCCr_pseudo: {
12216 F->insert(It, copy0MBB);
12217 F->insert(It, sinkMBB);
12220 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12226 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12242 .
addImm(
MI.getOperand(3).getImm())
12243 .
addReg(
MI.getOperand(4).getReg());
12258 .
addReg(
MI.getOperand(1).getReg())
12260 .
addReg(
MI.getOperand(2).getReg())
12263 MI.eraseFromParent();
12268 case ARM::BCCZi64: {
12274 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12279 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12283 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12289 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12293 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12303 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12312 MI.eraseFromParent();
12316 case ARM::Int_eh_sjlj_setjmp:
12317 case ARM::Int_eh_sjlj_setjmp_nofp:
12318 case ARM::tInt_eh_sjlj_setjmp:
12319 case ARM::t2Int_eh_sjlj_setjmp:
12320 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12323 case ARM::Int_eh_sjlj_setup_dispatch:
12324 EmitSjLjDispatchBlock(
MI, BB);
12347 Fn->
insert(BBI, SinkBB);
12349 Register ABSSrcReg =
MI.getOperand(1).getReg();
12350 Register ABSDstReg =
MI.getOperand(0).getReg();
12351 bool ABSSrcKIll =
MI.getOperand(1).isKill();
12352 bool isThumb2 = Subtarget->
isThumb2();
12356 Register NewRsbDstReg =
MRI.createVirtualRegister(
12357 isThumb2 ? &ARM::rGPRRegClass : &ARM::GPRRegClass);
12371 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12378 TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc)).
addMBB(SinkBB)
12385 TII->get(isThumb2 ? ARM::t2RSBri : ARM::RSBri), NewRsbDstReg)
12394 TII->get(ARM::PHI), ABSDstReg)
12399 MI.eraseFromParent();
12404 case ARM::COPY_STRUCT_BYVAL_I32:
12406 return EmitStructByval(
MI, BB);
12407 case ARM::WIN__CHKSTK:
12408 return EmitLowered__chkstk(
MI, BB);
12409 case ARM::WIN__DBZCHK:
12410 return EmitLowered__dbzchk(
MI, BB);
12427 if (!
Node->hasAnyUseOfValue(0)) {
12428 MI.getOperand(0).setIsDead(
true);
12430 if (!
Node->hasAnyUseOfValue(1)) {
12431 MI.getOperand(1).setIsDead(
true);
12435 for (
unsigned I = 0;
I !=
MI.getOperand(4).getImm(); ++
I) {
12436 Register TmpReg =
MRI.createVirtualRegister(isThumb1 ? &ARM::tGPRRegClass
12437 : &ARM::GPRRegClass);
12444 if (
MI.getOpcode() == ARM::MEMCPY) {
12462 MCID = &
TII->get(NewOpc);
12465 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12466 &&
"converted opcode should be the same except for cc_out"
12467 " (and, on Thumb1, pred)");
12477 MI.addOperand(
MI.getOperand(1));
12478 MI.removeOperand(1);
12482 for (
unsigned i =
MI.getNumOperands(); i--;) {
12484 if (
op.isReg() &&
op.isUse()) {
12487 MI.tieOperands(DefIdx, i);
12501 if (!
MI.hasOptionalDef() || !MCID->
operands()[ccOutIdx].isOptionalDef()) {
12502 assert(!NewOpc &&
"Optional cc_out operand required");
12507 bool definesCPSR =
false;
12508 bool deadCPSR =
false;
12509 for (
unsigned i = MCID->
getNumOperands(), e =
MI.getNumOperands(); i != e;
12513 definesCPSR =
true;
12516 MI.removeOperand(i);
12520 if (!definesCPSR) {
12521 assert(!NewOpc &&
"Optional cc_out operand required");
12524 assert(deadCPSR == !Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12526 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12527 "expect uninitialized optional cc_out operand");
12565 switch (
N->getOpcode()) {
12566 default:
return false;
12568 CC =
N->getOperand(0);
12590 EVT VT =
N->getValueType(0);
12591 CC =
N->getOperand(0);
12592 if (
CC.getValueType() != MVT::i1 ||
CC.getOpcode() !=
ISD::SETCC)
12638 EVT VT =
N->getValueType(0);
12641 bool SwapSelectOps;
12643 NonConstantVal, DAG))
12649 OtherOp, NonConstantVal);
12655 CCOp, TrueVal, FalseVal);
12679 if (
N->getOpcode() ==
ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12694 if (!
N->getValueType(0).is64BitVector())
12702 EVT VT =
N->getValueType(0);
12741 EVT VT =
N->getValueType(0);
12747 Opcode = Intrinsic::arm_neon_vpaddls;
12749 Opcode = Intrinsic::arm_neon_vpaddlu;
12777 EVT VT =
N->getValueType(0);
12792 unsigned nextIndex = 0;
12860 return DAG.
getNode(ExtOp, dl, VT, tmp);
12891 if (SRA.getOpcode() !=
ISD::SRA) {
12897 if (
auto Const = dyn_cast<ConstantSDNode>(SRA.getOperand(1))) {
12898 if (Const->getZExtValue() != 31)
12903 if (SRA.getOperand(0) !=
Mul)
12907 SDLoc dl(AddcNode);
12908 unsigned Opcode = 0;
12914 Op0 =
Mul.getOperand(0);
12915 Op1 =
Mul.getOperand(1);
12918 Op0 =
Mul.getOperand(0);
12919 Op1 =
Mul.getOperand(1).getOperand(0);
12922 Op0 =
Mul.getOperand(0).getOperand(0);
12923 Op1 =
Mul.getOperand(1);
12926 Op0 =
Mul->getOperand(0).getOperand(0);
12927 Op1 =
Mul->getOperand(1).getOperand(0);
12936 SDValue HiMLALResult(SMLAL.getNode(), 1);
12937 SDValue LoMLALResult(SMLAL.getNode(), 0);
12943 SDValue resNode(AddcNode, 0);
12972 "Expect an ADDE or SUBE");
12976 "ADDE node has the wrong inputs");
12995 "Expect ADDC with two result values. First: i32");
13015 bool IsLeftOperandMUL =
false;
13020 IsLeftOperandMUL =
true;
13031 SDValue *LowAddSub =
nullptr;
13034 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
13037 if (IsLeftOperandMUL)
13038 HiAddSub = &AddeSubeOp1;
13040 HiAddSub = &AddeSubeOp0;
13045 if (AddcSubcOp0 == MULOp.
getValue(0)) {
13046 LoMul = &AddcSubcOp0;
13047 LowAddSub = &AddcSubcOp1;
13049 if (AddcSubcOp1 == MULOp.
getValue(0)) {
13050 LoMul = &AddcSubcOp1;
13051 LowAddSub = &AddcSubcOp0;
13059 if (AddcSubcNode == HiAddSub->getNode() ||
13075 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
13089 return SDValue(AddeSubeNode, 0);
13100 DAG.
getVTList(MVT::i32, MVT::i32), Ops);
13110 return SDValue(AddeSubeNode, 0);
13122 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13131 SDNode *UmlalNode =
nullptr;
13156 DAG.
getVTList(MVT::i32, MVT::i32), Ops);
13170 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13175 SDNode* AddcNode =
N->getOperand(2).getNode();
13176 SDNode* AddeNode =
N->getOperand(3).getNode();
13184 {N->getOperand(0), N->getOperand(1),
13185 AddcNode->getOperand(0), AddcNode->getOperand(1)});
13209 int32_t imm =
C->getSExtValue();
13210 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
13215 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
13230 int64_t imm =
C->getSExtValue();
13241 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
13242 N->getOperand(0),
RHS,
N->getOperand(2));
13254 if (!Subtarget->hasMVEIntegerOps())
13267 SetCC =
N->getOperand(0);
13270 CC = cast<CondCodeSDNode>(SetCC->
getOperand(2))->get();
13271 TrueVal =
N->getOperand(1);
13272 FalseVal =
N->getOperand(2);
13274 LHS =
N->getOperand(0);
13275 RHS =
N->getOperand(1);
13276 CC = cast<CondCodeSDNode>(
N->getOperand(4))->get();
13277 TrueVal =
N->getOperand(2);
13278 FalseVal =
N->getOperand(3);
13283 unsigned int Opcode = 0;
13312 switch (TrueVal->getOpcode()) {
13331 if (TrueVal !=
LHS || FalseVal !=
RHS)
13334 EVT LeftType =
LHS->getValueType(0);
13335 EVT RightType =
RHS->getValueType(0);
13338 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13342 if (VectorScalarType != MVT::i32)
13350 if (VectorScalarType != MVT::i32)
13363 EVT VT =
N->getValueType(0);
13371 Shft =
N->getOperand(0);
13377 cast<CondCodeSDNode>(Cmp.getOperand(2))->get() !=
ISD::SETLT ||
13378 Cmp.getOperand(0) !=
N->getOperand(1) ||
13379 Cmp.getOperand(1) !=
N->getOperand(2))
13381 Shft =
N->getOperand(1);
13393 ScalarType = MVT::i8;
13396 case (1 << 15) - 1:
13397 ScalarType = MVT::i16;
13400 case (1ULL << 31) - 1:
13401 ScalarType = MVT::i32;
13432 unsigned LegalLanes = 128 / (ShftAmt + 1);
13456 for (
unsigned I = 0;
I < NumParts; ++
I) {
13473 if (!Subtarget->hasMVEIntegerOps())
13488 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13498 if (!Const || !Const->isOne())
13516 EVT VT =
N->getValueType(0);
13518 if (!Subtarget->hasMVEIntegerOps() ||
13547 Opc = Intrinsic::arm_mve_vctp64;
13550 Opc = Intrinsic::arm_mve_vctp32;
13553 Opc = Intrinsic::arm_mve_vctp16;
13556 Opc = Intrinsic::arm_mve_vctp8;
13610 EVT VT =
N->getValueType(0);
13616 switch (
Op.getOpcode()) {
13633 !isa<ConstantSDNode>(N0) && N1->
hasOneUse()) {
13641 unsigned N0RedOp = 0;
13648 unsigned N1RedOp = 0;
13662 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13664 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13671 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13685 LoadSDNode *Load0 = dyn_cast<LoadSDNode>(N0);
13686 LoadSDNode *Load1 = dyn_cast<LoadSDNode>(N1);
13695 if (!BaseLocDecomp0.getBase() ||
13696 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13697 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13699 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13701 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13711 if (IsBefore < 0) {
13714 }
else if (IsBefore > 0) {
13727 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13737 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13747 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13749 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13756 if (!Subtarget->hasMVEIntegerOps())
13762 EVT VT =
N->getValueType(0);
13767 if (VT != MVT::i64)
13778 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13796 std::tie(Ops[0], Ops[1]) = DAG.
SplitScalar(NA, dl, MVT::i32, MVT::i32);
13798 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13847 "Expected shift op");
13849 SDValue ShiftLHS =
N->getOperand(0);
13873 if (
auto *Const = dyn_cast<ConstantSDNode>(N1->
getOperand(1))) {
13874 if (Const->getAPIntValue().ult(256))
13877 Const->getAPIntValue().sgt(-256))
13893 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13894 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13895 "Expected XOR(SHIFT) pattern");
13898 auto *XorC = dyn_cast<ConstantSDNode>(
N->getOperand(1));
13899 auto *ShiftC = dyn_cast<ConstantSDNode>(
N->getOperand(0).getOperand(1));
13900 if (XorC && ShiftC) {
13901 unsigned MaskIdx, MaskLen;
13902 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13903 unsigned ShiftAmt = ShiftC->getZExtValue();
13904 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13905 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13906 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13907 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13917 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13919 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13920 "Expected shift-shift mask");
13933 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT);
13937 if (!Subtarget->hasNEON()) {
13956 return Subtarget->hasFP64();
13959 return Subtarget->hasMVEFloatOps();
13988 if (ST->isThumb() && ST->isThumb1Only())
13992 for (
auto *U :
N->users()) {
13993 switch(U->getOpcode()) {
14006 if (isa<ConstantSDNode>(U->getOperand(0)) ||
14007 isa<ConstantSDNode>(U->getOperand(1)))
14011 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
14012 U->getOperand(1).getOpcode() ==
ISD::SHL)
14022 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
14027 auto *C1ShlC2 = dyn_cast<ConstantSDNode>(
N->getOperand(1));
14028 auto *C2 = dyn_cast<ConstantSDNode>(SHL.getOperand(1));
14029 if (!C1ShlC2 || !C2)
14032 APInt C2Int = C2->getAPIntValue();
14033 APInt C1Int = C1ShlC2->getAPIntValue();
14035 if (C2Int.
uge(C2Width))
14041 if ((C1Int & Mask) != C1Int)
14048 auto LargeImm = [](
const APInt &Imm) {
14049 unsigned Zeros = Imm.countl_zero() + Imm.countr_zero();
14050 return Imm.getBitWidth() - Zeros > 8;
14053 if (LargeImm(C1Int) || LargeImm(C2Int))
14065 SHL.dump();
N->dump());
14100 if (CSINC.getOpcode() !=
ARMISD::CSINC || !CSINC.hasOneUse())
14109 CSINC.getOperand(0)),
14110 CSINC.getOperand(1), CSINC.getOperand(2),
14111 CSINC.getOperand(3));
14130 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
14172 if (!Subtarget->hasVMLxForwarding())
14191 EVT VT =
N->getValueType(0);
14202 EVT VT =
N->getValueType(0);
14203 if (VT != MVT::v2i64)
14212 EVT VT = cast<VTSDNode>(
Op->getOperand(1))->getVT();
14214 return Op->getOperand(0);
14228 And =
And->getOperand(0);
14233 Mask = Mask->getOperand(0);
14236 Mask.getValueType() != MVT::v4i32)
14242 return And->getOperand(0);
14247 if (
SDValue Op0 = IsSignExt(N0)) {
14248 if (
SDValue Op1 = IsSignExt(N1)) {
14254 if (
SDValue Op0 = IsZeroExt(N0)) {
14255 if (
SDValue Op1 = IsZeroExt(N1)) {
14270 EVT VT =
N->getValueType(0);
14271 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14282 if (VT != MVT::i32)
14289 int64_t MulAmt =
C->getSExtValue();
14290 unsigned ShiftAmt = llvm::countr_zero<uint64_t>(MulAmt);
14292 ShiftAmt = ShiftAmt & (32 - 1);
14297 MulAmt >>= ShiftAmt;
14300 if (llvm::has_single_bit<uint32_t>(MulAmt - 1)) {
14308 }
else if (llvm::has_single_bit<uint32_t>(MulAmt + 1)) {
14320 if (llvm::has_single_bit<uint32_t>(MulAmtAbs + 1)) {
14328 }
else if (llvm::has_single_bit<uint32_t>(MulAmtAbs - 1)) {
14358 if (
N->getValueType(0) != MVT::i32)
14367 if (C1 == 255 || C1 == 65535)
14370 SDNode *N0 =
N->getOperand(0).getNode();
14384 if (!C2 || C2 >= 32)
14428 if (Trailing == C2 && C2 + C3 < 32) {
14441 if (Leading == C2 && C2 + C3 < 32) {
14469 EVT VT =
N->getValueType(0);
14473 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14476 APInt SplatBits, SplatUndef;
14477 unsigned SplatBitSize;
14479 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14480 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14481 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14482 SplatBitSize == 64) {
14516 if (!Subtarget->hasV6Ops() ||
14517 (Subtarget->isThumb() &&
14518 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14521 SDValue SRL = OR->getOperand(0);
14522 SDValue SHL = OR->getOperand(1);
14525 SRL = OR->getOperand(1);
14526 SHL = OR->getOperand(0);
14533 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14537 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14538 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14539 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14558 unsigned Opcode = 0;
14559 if (
isS16(OpS16, DAG))
14577 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14580 EVT VT =
N->getValueType(0);
14595 if (VT != MVT::i32)
14608 if (Mask == 0xffff)
14615 if ((Val & ~Mask) != Val)
14640 (Mask == ~Mask2)) {
14643 if (Subtarget->hasDSP() &&
14644 (Mask == 0xffff || Mask == 0xffff0000))
14657 (~Mask == Mask2)) {
14660 if (Subtarget->hasDSP() &&
14661 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14734 EVT VT =
N->getValueType(0);
14739 auto IsFreelyInvertable = [&](
SDValue V) {
14746 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14762 EVT VT =
N->getValueType(0);
14768 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14769 VT == MVT::v8i1 || VT == MVT::v16i1))
14772 APInt SplatBits, SplatUndef;
14773 unsigned SplatBitSize;
14775 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14776 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14777 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14778 SplatBitSize == 64) {
14814 unsigned SplatBitSize;
14817 APInt SplatBits0, SplatBits1;
14821 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14822 HasAnyUndefs) && !HasAnyUndefs) {
14823 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14824 HasAnyUndefs) && !HasAnyUndefs) {
14829 SplatBits0 == ~SplatBits1) {
14859 EVT VT =
N->getValueType(0);
14874 if (Subtarget->hasMVEIntegerOps()) {
14905 ToMask = ~N->getConstantOperandAPInt(2);
14911 isa<ConstantSDNode>(
From->getOperand(1))) {
14912 APInt Shift =
From->getConstantOperandAPInt(1);
14925 unsigned LastActiveBitInA =
A.countr_zero();
14926 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
14927 return LastActiveBitInA - 1 == FirstActiveBitInB;
14932 APInt ToMask, FromMask;
14940 APInt NewToMask, NewFromMask;
14942 if (NewFrom !=
From)
14946 if ((NewToMask & ToMask).getBoolValue())
14971 unsigned InvMask =
N->getConstantOperandVal(2);
14973 unsigned Width = llvm::bit_width<unsigned>(~InvMask) - LSB;
14975 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
14976 "undefined behavior");
14977 unsigned Mask = (1u << Width) - 1;
14979 if ((Mask & (~Mask2)) == 0)
14981 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
14988 APInt ToMask1, FromMask1;
14991 APInt ToMask2, FromMask2;
14997 APInt NewFromMask = FromMask1 | FromMask2;
14998 APInt NewToMask = ToMask1 | ToMask2;
15000 EVT VT =
N->getValueType(0);
15003 if (NewFromMask[0] == 0)
15015 APInt ToMask1 = ~N->getConstantOperandAPInt(2);
15016 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
15018 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
15022 EVT VT =
N->getValueType(0);
15025 N->getOperand(1),
N->getOperand(2));
15039 SDValue CSInc = Cmp->getOperand(0);
15089 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
15090 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15093 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
15095 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15108 SDValue InDouble =
N->getOperand(0);
15117 !cast<LoadSDNode>(InNode)->isVolatile()) {
15123 SDValue BasePtr = LD->getBasePtr();
15125 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
15126 LD->getAlign(), LD->getMemOperand()->getFlags());
15132 LD->getPointerInfo().getWithOffset(4),
15134 LD->getMemOperand()->getFlags());
15146 isa<ConstantSDNode>(InDouble.
getOperand(1))) {
15167 if (!Subtarget->
isLittle() && BVSwap)
15177 if (isa<ConstantSDNode>(BV.
getOperand(2))) {
15185 if (!Subtarget->
isLittle() && BVSwap)
15230 if (Copy.getValueType() == MVT::f32 &&
15232 bool HasGlue = Copy->getNumOperands() == 3;
15233 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
15234 HasGlue ? Copy->getOperand(2) :
SDValue()};
15235 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
15253 if (
LoadSDNode *LN0 = dyn_cast<LoadSDNode>(Op0)) {
15254 if (LN0->hasOneUse() && LN0->isUnindexed() &&
15255 LN0->getMemoryVT() == MVT::i16) {
15258 LN0->getBasePtr(), LN0->getMemOperand());
15276 EVT VT =
N->getValueType(0);
15310 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15311 for (
unsigned i = 0; i < NumElts; ++i) {
15312 SDNode *Elt =
N->getOperand(i).getNode();
15329 if (
N->getNumOperands() == 2)
15335 EVT VT =
N->getValueType(0);
15341 for (
unsigned i = 0; i < NumElts; ++i) {
15367 EVT VT =
N->getValueType(0);
15375 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15380 Use->getValueType(0).isFloatingPoint())
15388 unsigned NumOfBitCastedElts = 0;
15390 unsigned NumOfRelevantElts = NumElts;
15391 for (
unsigned Idx = 0;
Idx < NumElts; ++
Idx) {
15396 ++NumOfBitCastedElts;
15397 }
else if (Elt.
isUndef() || isa<ConstantSDNode>(Elt))
15400 --NumOfRelevantElts;
15404 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15422 for (
unsigned Idx = 0 ;
Idx < NumElts; ++
Idx) {
15427 V->getOperand(0).getValueType() == MVT::i32)
15429 V = V.getOperand(0);
15446 EVT VT =
N->getValueType(0);
15453 if (
Op->getOperand(0).getValueType() == VT)
15454 return Op->getOperand(0);
15469 if (
Op.getValueType() == MVT::i32) {
15480 EVT VT =
N->getValueType(0);
15485 if (ST->isLittle())
15489 if (
Op.getValueType() == VT)
15498 if (
Op->getOperand(0).getValueType() == VT)
15499 return Op->getOperand(0);
15508 if (!Subtarget->hasMVEIntegerOps())
15511 EVT VT =
N->getValueType(0);
15542 EVT VT =
N->getValueType(0);
15543 SDNode *Elt =
N->getOperand(1).getNode();
15558 Vec, V,
N->getOperand(2));
15568 EVT VT =
N->getValueType(0);
15577 Ext.getOperand(0).getValueType() == MVT::f32)
15578 Ext = Ext.getOperand(0);
15580 !isa<ConstantSDNode>(Ext.getOperand(1)) ||
15581 Ext.getConstantOperandVal(1) % 2 != 0)
15583 if (Ext->hasOneUse() && (Ext->user_begin()->getOpcode() ==
ISD::SINT_TO_FP ||
15587 SDValue Op0 = Ext.getOperand(0);
15590 unsigned Lane = Ext.getConstantOperandVal(1);
15596 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15597 isa<ConstantSDNode>(V->getOperand(1)) &&
15598 V->getConstantOperandVal(1) == Lane + 1 &&
15599 V->getOperand(0).getResNo() == ResNo;
15601 if (OtherIt == Op0->
users().end())
15606 SDValue OtherExt(*OtherIt, 0);
15619 DCI.
DAG.
getConstant(Ext.getConstantOperandVal(1) / 2, dl, MVT::i32));
15631 EVT VT =
N->getValueType(0);
15637 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15639 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15641 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15644 while (
X.getValueType() != VT &&
X->getOpcode() ==
ISD::BITCAST)
15645 X =
X->getOperand(0);
15646 if (
X.getValueType() == VT)
15652 isa<ConstantSDNode>(
N->getOperand(1)) &&
15654 return Op0.
getOperand(
N->getConstantOperandVal(1));
15659 isa<ConstantSDNode>(
N->getOperand(1)) &&
15664 unsigned Offset =
N->getConstantOperandVal(1);
15676 unsigned Idx =
N->getConstantOperandVal(1);
15690 EVT VT =
N->getValueType(0);
15694 cast<VTSDNode>(
N->getOperand(1))->getVT() ==
15695 Op.getOperand(0).getValueType().getScalarType())
15705 SDValue SubVec =
N->getOperand(1);
15706 uint64_t IdxVal =
N->getConstantOperandVal(2);
15717 if (IdxVal == 0 && Vec.
isUndef())
15723 (IdxVal != 0 && IdxVal != NumSubElts))
15796 EVT VT =
N->getValueType(0);
15807 unsigned HalfElts = NumElts/2;
15809 for (
unsigned n = 0; n < NumElts; ++n) {
15812 if (MaskElt < (
int)HalfElts)
15814 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
15815 NewElt = HalfElts + MaskElt - NumElts;
15842 bool SimpleConstIncOnly,
15850 bool isLoadOp =
true;
15851 bool isLaneOp =
false;
15854 bool hasAlignment =
true;
15855 unsigned NewOpc = 0;
15856 unsigned NumVecs = 0;
15857 if (
Target.isIntrinsic) {
15858 unsigned IntNo =
N->getConstantOperandVal(1);
15862 case Intrinsic::arm_neon_vld1:
15866 case Intrinsic::arm_neon_vld2:
15870 case Intrinsic::arm_neon_vld3:
15874 case Intrinsic::arm_neon_vld4:
15878 case Intrinsic::arm_neon_vld1x2:
15881 hasAlignment =
false;
15883 case Intrinsic::arm_neon_vld1x3:
15886 hasAlignment =
false;
15888 case Intrinsic::arm_neon_vld1x4:
15891 hasAlignment =
false;
15893 case Intrinsic::arm_neon_vld2dup:
15897 case Intrinsic::arm_neon_vld3dup:
15901 case Intrinsic::arm_neon_vld4dup:
15905 case Intrinsic::arm_neon_vld2lane:
15910 case Intrinsic::arm_neon_vld3lane:
15915 case Intrinsic::arm_neon_vld4lane:
15920 case Intrinsic::arm_neon_vst1:
15925 case Intrinsic::arm_neon_vst2:
15930 case Intrinsic::arm_neon_vst3:
15935 case Intrinsic::arm_neon_vst4:
15940 case Intrinsic::arm_neon_vst2lane:
15946 case Intrinsic::arm_neon_vst3lane:
15952 case Intrinsic::arm_neon_vst4lane:
15958 case Intrinsic::arm_neon_vst1x2:
15962 hasAlignment =
false;
15964 case Intrinsic::arm_neon_vst1x3:
15968 hasAlignment =
false;
15970 case Intrinsic::arm_neon_vst1x4:
15974 hasAlignment =
false;
15979 switch (
N->getOpcode()) {
16015 VecTy =
N->getValueType(0);
16016 }
else if (
Target.isIntrinsic) {
16017 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
16020 "Node has to be a load, a store, or an intrinsic!");
16021 VecTy =
N->getOperand(1).getValueType();
16029 if (isLaneOp || isVLDDUPOp)
16032 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
16038 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
16044 EVT AlignedVecTy = VecTy;
16061 if (isa<LSBaseSDNode>(
N)) {
16064 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
16065 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
16076 Alignment =
Align(1);
16082 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16084 for (n = 0; n < NumResultVecs; ++n)
16085 Tys[n] = AlignedVecTy;
16086 Tys[n++] = MVT::i32;
16087 Tys[n] = MVT::Other;
16102 unsigned LastOperand =
16103 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
16104 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
16113 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::STORE) {
16124 for (
unsigned i = 0; i < NumResultVecs; ++i)
16129 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::LOAD) {
16130 SDValue &LdVal = NewResults[0];
16166 switch (
N->getOpcode()) {
16169 if (isa<ConstantSDNode>(
N->getOperand(1))) {
16170 *
Ptr =
N->getOperand(0);
16171 *CInc =
N->getOperand(1);
16177 if (isa<ConstantSDNode>(
N->getOperand(2))) {
16178 *
Ptr =
N->getOperand(1);
16179 *CInc =
N->getOperand(2);
16228 unsigned ConstInc =
16250 unsigned UserOffset =
16253 if (!UserOffset || UserOffset <=
Offset)
16256 unsigned NewConstInc = UserOffset -
Offset;
16266 unsigned NumValidUpd = BaseUpdates.
size();
16267 for (
unsigned I = 0;
I < NumValidUpd;) {
16271 std::swap(BaseUpdates[
I], BaseUpdates[NumValidUpd]);
16279 BaseUpdates.
resize(NumValidUpd);
16284 std::stable_sort(BaseUpdates.
begin(), BaseUpdates.
end(),
16286 return LHS.ConstInc < RHS.ConstInc;
16315 unsigned IntNo =
N->getConstantOperandVal(1);
16316 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16318 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16340 bool isLoadOp =
true;
16341 unsigned NewOpc = 0;
16342 unsigned NumVecs = 0;
16346 case Intrinsic::arm_mve_vld2q:
16350 case Intrinsic::arm_mve_vld4q:
16354 case Intrinsic::arm_mve_vst2q:
16359 case Intrinsic::arm_mve_vst4q:
16369 VecTy =
N->getValueType(0);
16371 VecTy =
N->getOperand(3).getValueType();
16385 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16387 for (n = 0; n < NumResultVecs; ++n)
16389 Tys[n++] = MVT::i32;
16390 Tys[n] = MVT::Other;
16399 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16407 for (
unsigned i = 0; i < NumResultVecs; ++i)
16426 EVT VT =
N->getValueType(0);
16432 SDNode *VLD =
N->getOperand(0).getNode();
16435 unsigned NumVecs = 0;
16436 unsigned NewOpc = 0;
16438 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16441 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16444 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16456 if (
Use.getResNo() == NumVecs)
16460 VLDLaneNo !=
User->getConstantOperandVal(1))
16467 for (n = 0; n < NumVecs; ++n)
16469 Tys[n] = MVT::Other;
16479 unsigned ResNo =
Use.getResNo();
16481 if (ResNo == NumVecs)
16488 std::vector<SDValue> VLDDupResults;
16489 for (
unsigned n = 0; n < NumVecs; ++n)
16503 EVT VT =
N->getValueType(0);
16506 if (Subtarget->hasMVEIntegerOps()) {
16510 ExtractVT = MVT::i32;
16512 N->getOperand(0),
N->getOperand(1));
16524 Op =
Op.getOperand(0);
16529 unsigned EltSize =
Op.getScalarValueSizeInBits();
16531 unsigned Imm =
Op.getConstantOperandVal(0);
16547 if (Subtarget->hasMVEIntegerOps()) {
16550 if (
Op.getValueType() == MVT::f32)
16553 else if (
Op.getValueType() == MVT::f16)
16558 if (!Subtarget->hasNEON())
16565 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16566 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16567 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16572 LD->getMemoryVT(), LD->getMemOperand());
16583 EVT VT =
N->getValueType(0);
16605 assert(StVT != VT &&
"Cannot truncate to the same type");
16615 if (0 != (NumElems * FromEltSz) % ToEltSz)
16618 unsigned SizeRatio = FromEltSz / ToEltSz;
16623 NumElems * SizeRatio);
16629 for (
unsigned i = 0; i < NumElems; ++i)
16643 MVT StoreType = MVT::i8;
16645 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16664 unsigned E = (ToEltSz * NumElems) / StoreType.
getSizeInBits();
16665 for (
unsigned I = 0;
I < E;
I++) {
16696 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16699 unsigned NumElements = 4;
16716 unsigned Off0 = Rev ? NumElts : 0;
16717 unsigned Off1 = Rev ? 0 : NumElts;
16719 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16720 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16722 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16729 if (
auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(Trunc.
getOperand(0)))
16730 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16750 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16765 NewToVT, Alignment, MMOFlags, AAInfo);
16798 unsigned NewOffset =
16806 NewToVT, Alignment, MMOFlags, AAInfo);
16828 {Extract.getOperand(0), Extract.getOperand(1)});
16859 if (Subtarget->hasNEON())
16863 if (Subtarget->hasMVEFloatOps())
16867 if (Subtarget->hasMVEIntegerOps()) {
16943 if (!Subtarget->hasNEON())
16947 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
16952 if (!isa<BuildVectorSDNode>(ConstVec))
16955 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
16957 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
16959 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
16960 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
16971 if (
C == -1 ||
C == 0 ||
C > 32)
16976 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
16977 Intrinsic::arm_neon_vcvtfp2fxu;
16980 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
16983 if (IntBits < FloatBits)
16991 if (!Subtarget->hasMVEFloatOps())
16999 EVT VT =
N->getValueType(0);
17004 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
17008 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
17009 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
17011 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
17024 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
17035 EVT VT =
N->getValueType(0);
17038 if (!
N->getFlags().hasAllowReassociation())
17045 unsigned Opc =
A.getConstantOperandVal(0);
17046 if (Opc != Intrinsic::arm_mve_vcmlaq)
17051 A.getOperand(3),
A.getOperand(4));
17083 if (!Subtarget->hasNEON())
17087 unsigned OpOpcode =
Op.getNode()->getOpcode();
17088 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
17092 SDValue ConstVec =
N->getOperand(1);
17093 if (!isa<BuildVectorSDNode>(ConstVec))
17096 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
17098 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
17100 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17101 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17121 int32_t
C = IntVal.exactLogBase2();
17122 if (
C == -1 ||
C == 0 ||
C > 32)
17128 if (IntBits < FloatBits)
17130 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
17132 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
17133 : Intrinsic::arm_neon_vcvtfxu2fp;
17141 if (!ST->hasMVEIntegerOps())
17145 EVT ResVT =
N->getValueType(0);
17173 EVT AVT =
A.getValueType();
17179 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
17180 EVT AVT =
A.getValueType();
17192 if (ExtTypeMatches(
A, ExtTypes))
17193 return ExtendIfNeeded(
A, ExtendCode);
17196 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
17203 if (Ext->getOpcode() != ExtendCode)
17206 if (ExtTypeMatches(
A, ExtTypes))
17207 return ExtendIfNeeded(
A, ExtendCode);
17220 if (ResVT !=
RetTy)
17223 if (
Mul->getOpcode() == ExtendCode &&
17224 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17226 Mul =
Mul->getOperand(0);
17235 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17236 A = ExtendIfNeeded(
A, ExtendCode);
17237 B = ExtendIfNeeded(
B, ExtendCode);
17255 if (
Mul->getOpcode() == ExtendCode &&
17256 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17258 Mul =
Mul->getOperand(0);
17267 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17268 A = ExtendIfNeeded(
A, ExtendCode);
17269 B = ExtendIfNeeded(
B, ExtendCode);
17280 EVT VT = Ops[0].getValueType();
17281 if (VT == MVT::v16i8) {
17283 "Unexpected illegal long reduction opcode");
17288 DAG.
getVTList(MVT::v8i16, MVT::v8i16), Ops[0]);
17291 DAG.
getVTList(MVT::v8i16, MVT::v8i16), Ops[1]);
17312 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17315 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17379 Op =
Op->getOperand(1);
17381 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17383 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17400 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17401 auto *Shuf = dyn_cast<ShuffleVectorSDNode>(
N->getOperand(VecOp));
17402 if (!Shuf || !Shuf->getOperand(1).isUndef())
17407 APInt SetElts(Mask.size(), 0);
17408 for (
int E : Mask) {
17409 if (E < 0 || E >= (
int)Mask.size())
17416 if (
N->getNumOperands() != VecOp + 1) {
17417 auto *Shuf2 = dyn_cast<ShuffleVectorSDNode>(
N->getOperand(VecOp + 1));
17418 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17424 if (
Op.getValueType().isVector())
17436 unsigned IsTop =
N->getConstantOperandVal(2);
17443 if (Op0->
isUndef() && !IsTop)
17457 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17459 APInt Op0DemandedElts =
17460 IsTop ? Op1DemandedElts
17475 unsigned IsTop =
N->getConstantOperandVal(2);
17477 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17478 APInt Op0DemandedElts =
17490 EVT VT =
N->getValueType(0);
17494 auto *Shuf0 = dyn_cast<ShuffleVectorSDNode>(
LHS);
17495 auto *Shuf1 = dyn_cast<ShuffleVectorSDNode>(
RHS);
17497 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17498 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17502 LHS.getOperand(0),
RHS.getOperand(0));
17516 if (
auto C = dyn_cast<ConstantSDNode>(
N->getOperand(2))) {
17517 int ShiftAmt =
C->getSExtValue();
17518 if (ShiftAmt == 0) {
17524 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17525 unsigned NewOpcode =
17541 unsigned IntNo =
N->getConstantOperandVal(0);
17552 case Intrinsic::arm_neon_vshifts:
17553 case Intrinsic::arm_neon_vshiftu:
17554 case Intrinsic::arm_neon_vrshifts:
17555 case Intrinsic::arm_neon_vrshiftu:
17556 case Intrinsic::arm_neon_vrshiftn:
17557 case Intrinsic::arm_neon_vqshifts:
17558 case Intrinsic::arm_neon_vqshiftu:
17559 case Intrinsic::arm_neon_vqshiftsu:
17560 case Intrinsic::arm_neon_vqshiftns:
17561 case Intrinsic::arm_neon_vqshiftnu:
17562 case Intrinsic::arm_neon_vqshiftnsu:
17563 case Intrinsic::arm_neon_vqrshiftns:
17564 case Intrinsic::arm_neon_vqrshiftnu:
17565 case Intrinsic::arm_neon_vqrshiftnsu: {
17566 EVT VT =
N->getOperand(1).getValueType();
17568 unsigned VShiftOpc = 0;
17571 case Intrinsic::arm_neon_vshifts:
17572 case Intrinsic::arm_neon_vshiftu:
17577 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17584 case Intrinsic::arm_neon_vrshifts:
17585 case Intrinsic::arm_neon_vrshiftu:
17590 case Intrinsic::arm_neon_vqshifts:
17591 case Intrinsic::arm_neon_vqshiftu:
17596 case Intrinsic::arm_neon_vqshiftsu:
17601 case Intrinsic::arm_neon_vrshiftn:
17602 case Intrinsic::arm_neon_vqshiftns:
17603 case Intrinsic::arm_neon_vqshiftnu:
17604 case Intrinsic::arm_neon_vqshiftnsu:
17605 case Intrinsic::arm_neon_vqrshiftns:
17606 case Intrinsic::arm_neon_vqrshiftnu:
17607 case Intrinsic::arm_neon_vqrshiftnsu:
17619 case Intrinsic::arm_neon_vshifts:
17620 case Intrinsic::arm_neon_vshiftu:
17623 case Intrinsic::arm_neon_vrshifts:
17626 case Intrinsic::arm_neon_vrshiftu:
17629 case Intrinsic::arm_neon_vrshiftn:
17632 case Intrinsic::arm_neon_vqshifts:
17635 case Intrinsic::arm_neon_vqshiftu:
17638 case Intrinsic::arm_neon_vqshiftsu:
17641 case Intrinsic::arm_neon_vqshiftns:
17644 case Intrinsic::arm_neon_vqshiftnu:
17647 case Intrinsic::arm_neon_vqshiftnsu:
17650 case Intrinsic::arm_neon_vqrshiftns:
17653 case Intrinsic::arm_neon_vqrshiftnu:
17656 case Intrinsic::arm_neon_vqrshiftnsu:
17662 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17663 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
17666 case Intrinsic::arm_neon_vshiftins: {
17667 EVT VT =
N->getOperand(1).getValueType();
17669 unsigned VShiftOpc = 0;
17673 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
17680 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17681 N->getOperand(1),
N->getOperand(2),
17685 case Intrinsic::arm_neon_vqrshifts:
17686 case Intrinsic::arm_neon_vqrshiftu:
17690 case Intrinsic::arm_neon_vbsl: {
17693 N->getOperand(2),
N->getOperand(3));
17695 case Intrinsic::arm_mve_vqdmlah:
17696 case Intrinsic::arm_mve_vqdmlash:
17697 case Intrinsic::arm_mve_vqrdmlah:
17698 case Intrinsic::arm_mve_vqrdmlash:
17699 case Intrinsic::arm_mve_vmla_n_predicated:
17700 case Intrinsic::arm_mve_vmlas_n_predicated:
17701 case Intrinsic::arm_mve_vqdmlah_predicated:
17702 case Intrinsic::arm_mve_vqdmlash_predicated:
17703 case Intrinsic::arm_mve_vqrdmlah_predicated:
17704 case Intrinsic::arm_mve_vqrdmlash_predicated: {
17709 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
17716 case Intrinsic::arm_mve_minv:
17717 case Intrinsic::arm_mve_maxv:
17718 case Intrinsic::arm_mve_minav:
17719 case Intrinsic::arm_mve_maxav:
17720 case Intrinsic::arm_mve_minv_predicated:
17721 case Intrinsic::arm_mve_maxv_predicated:
17722 case Intrinsic::arm_mve_minav_predicated:
17723 case Intrinsic::arm_mve_maxav_predicated: {
17726 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
17733 case Intrinsic::arm_mve_addv: {
17736 bool Unsigned =
N->getConstantOperandVal(2);
17741 case Intrinsic::arm_mve_addlv:
17742 case Intrinsic::arm_mve_addlv_predicated: {
17745 bool Unsigned =
N->getConstantOperandVal(2);
17746 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
17751 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
17774 EVT VT =
N->getValueType(0);
17776 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
17777 N->getOperand(0)->getOpcode() ==
ISD::AND &&
17778 N->getOperand(0)->hasOneUse()) {
17786 ConstantSDNode *ShiftAmtNode = dyn_cast<ConstantSDNode>(
N->getOperand(1));
17795 if (AndMask == 255 || AndMask == 65535)
17799 if (MaskedBits > ShiftAmt) {
17814 if (ST->hasMVEIntegerOps())
17819 switch (
N->getOpcode()) {
17832 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
17833 unsigned VShiftOpc =
17836 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
17852 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
17855 EVT FromVT = LD->getValueType(0);
17856 EVT ToVT =
N->getValueType(0);
17863 unsigned NumElements = 0;
17864 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
17866 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
17868 if (NumElements == 0 ||
17878 SDValue BasePtr = LD->getBasePtr();
17879 Align Alignment = LD->getOriginalAlign();
17900 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
17901 Alignment, MMOFlags, AAInfo);
17907 if (FromEltVT == MVT::f16) {
17910 for (
unsigned i = 0; i < Loads.
size(); i++) {
17936 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
17940 EVT VT =
N->getValueType(0);
17944 if (VT == MVT::i32 &&
17945 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
17947 isa<ConstantSDNode>(Lane)) {
17950 switch (
N->getOpcode()) {
17964 if (ST->hasMVEIntegerOps())
17973 if (ST->hasMVEFloatOps())
17984 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
17988 EVT VT =
Op.getValueType();
17991 if (VT != MVT::i32 ||
17993 !isa<ConstantSDNode>(
Op.getOperand(1)) ||
18004 APInt MaxC = Max.getConstantOperandAPInt(1);
18007 !(MinC + 1).isPowerOf2())
18025 EVT VT =
N->getValueType(0);
18028 if (VT == MVT::i32)
18031 if (!ST->hasMVEIntegerOps())
18037 if (VT != MVT::v4i32 && VT != MVT::v8i16)
18040 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
18048 if (VT == MVT::v4i32)
18049 SaturateC =
APInt(32, (1 << 15) - 1,
true);
18051 SaturateC =
APInt(16, (1 << 7) - 1,
true);
18058 MaxC != ~SaturateC)
18063 if (IsSignedSaturate(
N, N0.
getNode())) {
18066 if (VT == MVT::v4i32) {
18067 HalfVT = MVT::v8i16;
18068 ExtVT = MVT::v4i16;
18070 HalfVT = MVT::v16i8;
18085 auto IsUnsignedSaturate = [&](
SDNode *Min) {
18091 if (VT == MVT::v4i32)
18092 SaturateC =
APInt(32, (1 << 16) - 1,
true);
18094 SaturateC =
APInt(16, (1 << 8) - 1,
true);
18103 if (IsUnsignedSaturate(
N)) {
18107 if (VT == MVT::v4i32) {
18108 HalfVT = MVT::v8i16;
18109 ExtConst = 0x0000FFFF;
18111 HalfVT = MVT::v16i8;
18133 const APInt *CV = &
C->getAPIntValue();
18151 SDValue Op0 = CMOV->getOperand(0);
18152 SDValue Op1 = CMOV->getOperand(1);
18153 auto CC = CMOV->getConstantOperandAPInt(2).getLimitedValue();
18154 SDValue CmpZ = CMOV->getOperand(3);
18190 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
18197 if ((OrCI & Known.
Zero) != OrCI)
18203 EVT VT =
X.getValueType();
18204 unsigned BitInX = AndC->
logBase2();
18212 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
18213 BitInY < NumActiveBits; ++BitInY) {
18214 if (OrCI[BitInY] == 0)
18217 Mask.setBit(BitInY);
18234 switch (
N->getOpcode()) {
18238 if (!isa<ConstantSDNode>(
N.getOperand(1)))
18240 if (!cast<ConstantSDNode>(
N.getOperand(1))->isOne())
18246 auto *Const = dyn_cast<ConstantSDNode>(
N.getOperand(1));
18249 if (Const->isZero())
18251 else if (Const->isOne())
18255 CC = cast<CondCodeSDNode>(
N.getOperand(2))->get();
18259 unsigned IntOp =
N.getConstantOperandVal(1);
18260 if (IntOp != Intrinsic::test_start_loop_iterations &&
18261 IntOp != Intrinsic::loop_decrement_reg)
18287 bool Negate =
false;
18293 Cond =
N->getOperand(1);
18294 Dest =
N->getOperand(2);
18297 CC = cast<CondCodeSDNode>(
N->getOperand(1))->get();
18298 Cond =
N->getOperand(2);
18299 Dest =
N->getOperand(4);
18300 if (
auto *Const = dyn_cast<ConstantSDNode>(
N->getOperand(3))) {
18301 if (!Const->isOne() && !Const->isZero())
18303 Imm = Const->getZExtValue();
18331 assert((IsTrueIfZero(
CC, Imm) || IsFalseIfZero(
CC, Imm)) &&
18332 "unsupported condition");
18337 unsigned IntOp =
Int->getConstantOperandVal(1);
18338 assert((
N->hasOneUse() &&
N->user_begin()->getOpcode() ==
ISD::BR) &&
18339 "expected single br user");
18340 SDNode *Br = *
N->user_begin();
18350 if (IntOp == Intrinsic::test_start_loop_iterations) {
18354 if (IsTrueIfZero(
CC, Imm)) {
18355 SDValue Ops[] = {Chain, Setup, Dest};
18360 UpdateUncondBr(Br, Dest, DAG);
18362 SDValue Ops[] = {Chain, Setup, OtherTarget};
18375 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18383 if (
Target == OtherTarget)
18384 UpdateUncondBr(Br, Dest, DAG);
18420 LHS->getOperand(0)->getOperand(2),
18421 LHS->getOperand(0)->getOperand(3));
18435 EVT VT =
N->getValueType(0);
18439 SDValue FalseVal =
N->getOperand(0);
18440 SDValue TrueVal =
N->getOperand(1);
18445 if (!Subtarget->
isThumb1Only() && Subtarget->hasV6T2Ops()) {
18483 LHS->getOperand(2),
LHS->getOperand(3));
18493 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18497 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18499 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18508 if (!Subtarget->
isThumb1Only() && Subtarget->hasV5TOps()) {
18573 const APInt *TrueConst;
18575 ((FalseVal.getOpcode() ==
ARMISD::SUBC && FalseVal.getOperand(0) ==
LHS &&
18576 FalseVal.getOperand(1) ==
RHS) ||
18580 unsigned ShiftAmount = TrueConst->
logBase2();
18595 if (Known.
Zero == 0xfffffffe)
18598 else if (Known.
Zero == 0xffffff00)
18601 else if (Known.
Zero == 0xffff0000)
18614 EVT DstVT =
N->getValueType(0);
18617 if (ST->hasMVEIntegerOps() && Src.getOpcode() ==
ARMISD::VDUP) {
18618 EVT SrcVT = Src.getValueType();
18626 Src.getOperand(0).getValueType().getScalarSizeInBits() <=
18627 Src.getValueType().getScalarSizeInBits())
18628 Src = Src.getOperand(0);
18632 EVT SrcVT = Src.getValueType();
18652 EVT VT =
N->getValueType(0);
18660 if (
N->getNumOperands() == 2 &&
18664 N->getOperand(0).getOperand(1),
18665 N->getOperand(1).getOperand(0),
18666 N->getOperand(1).getOperand(1));
18669 if (
N->getNumOperands() == 2 &&
18672 auto *S0 = cast<ShuffleVectorSDNode>(
N->getOperand(0).getNode());
18673 auto *
S1 = cast<ShuffleVectorSDNode>(
N->getOperand(1).getNode());
18675 if (S0->getOperand(0) ==
S1->getOperand(0) &&
18676 S0->getOperand(1) ==
S1->getOperand(1)) {
18679 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
18699 return Op.getOpcode() == ISD::BUILD_VECTOR ||
18700 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
18701 (Op.getOpcode() == ISD::BITCAST &&
18702 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
18705 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
18707 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
18724 int SPFI = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
18725 int NumIns =
N->getNumOperands();
18726 assert((NumIns == 2 || NumIns == 4) &&
18727 "Expected 2 or 4 inputs to an MVETrunc");
18729 if (
N->getNumOperands() == 4)
18733 for (
int I = 0;
I < NumIns;
I++) {
18735 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18755 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
18758 EVT FromVT = LD->getMemoryVT();
18759 EVT ToVT =
N->getValueType(0);
18766 unsigned NumElements = 0;
18767 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
18769 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
18771 assert(NumElements != 0);
18777 LD->getExtensionType() != NewExtType)
18784 SDValue BasePtr = LD->getBasePtr();
18785 Align Alignment = LD->getOriginalAlign();
18804 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18805 Alignment, MMOFlags, AAInfo);
18821 EVT VT =
N->getValueType(0);
18823 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
18824 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
18826 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18828 auto Extend = [&](
SDValue V) {
18838 SDValue Ext = Extend(
N->getOperand(0));
18843 if (
auto *SVN = dyn_cast<ShuffleVectorSDNode>(
N->getOperand(0))) {
18846 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
18851 auto CheckInregMask = [&](
int Start,
int Offset) {
18859 if (CheckInregMask(0, 0))
18861 else if (CheckInregMask(0, 1))
18862 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18863 else if (CheckInregMask(0, Mask.size()))
18865 else if (CheckInregMask(0, Mask.size() + 1))
18866 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18871 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18875 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18882 if (
N->getOperand(0)->getOpcode() ==
ISD::LOAD)
18892 int SPFI = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
18893 int NumOuts =
N->getNumValues();
18894 assert((NumOuts == 2 || NumOuts == 4) &&
18895 "Expected 2 or 4 outputs to an MVEEXT");
18896 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18898 if (
N->getNumOperands() == 4)
18904 StackPtr, MPI,
Align(4));
18907 for (
int I = 0;
I < NumOuts;
I++) {
18909 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18910 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
18915 VT, Chain,
Ptr, MPI, LoadVT,
Align(4));
18924 switch (
N->getOpcode()) {
19041 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19048 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19059 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19067 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
19069 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
19077 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
19079 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
19087 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19098 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19106 if (
N->getOperand(1) ==
N->getOperand(2))
19107 return N->getOperand(1);
19111 switch (
N->getConstantOperandVal(1)) {
19112 case Intrinsic::arm_neon_vld1:
19113 case Intrinsic::arm_neon_vld1x2:
19114 case Intrinsic::arm_neon_vld1x3:
19115 case Intrinsic::arm_neon_vld1x4:
19116 case Intrinsic::arm_neon_vld2:
19117 case Intrinsic::arm_neon_vld3:
19118 case Intrinsic::arm_neon_vld4:
19119 case Intrinsic::arm_neon_vld2lane:
19120 case Intrinsic::arm_neon_vld3lane:
19121 case Intrinsic::arm_neon_vld4lane:
19122 case Intrinsic::arm_neon_vld2dup:
19123 case Intrinsic::arm_neon_vld3dup:
19124 case Intrinsic::arm_neon_vld4dup:
19125 case Intrinsic::arm_neon_vst1:
19126 case Intrinsic::arm_neon_vst1x2:
19127 case Intrinsic::arm_neon_vst1x3:
19128 case Intrinsic::arm_neon_vst1x4:
19129 case Intrinsic::arm_neon_vst2:
19130 case Intrinsic::arm_neon_vst3:
19131 case Intrinsic::arm_neon_vst4:
19132 case Intrinsic::arm_neon_vst2lane:
19133 case Intrinsic::arm_neon_vst3lane:
19134 case Intrinsic::arm_neon_vst4lane:
19136 case Intrinsic::arm_mve_vld2q:
19137 case Intrinsic::arm_mve_vld4q:
19138 case Intrinsic::arm_mve_vst2q:
19139 case Intrinsic::arm_mve_vst4q:
19156 unsigned *
Fast)
const {
19165 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
19167 if (AllowsUnaligned) {
19169 *
Fast = Subtarget->hasV7Ops();
19174 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
19178 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->
isLittle())) {
19185 if (!Subtarget->hasMVEIntegerOps())
19189 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
19190 Ty == MVT::v2i1)) {
19198 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
19214 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
19215 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
19216 Ty == MVT::v2f64) {
19229 if ((
Op.isMemcpy() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
19230 !FuncAttributes.
hasFnAttr(Attribute::NoImplicitFloat)) {
19232 if (
Op.size() >= 16 &&
19238 }
else if (
Op.size() >= 8 &&
19259 return (SrcBits == 64 && DestBits == 32);
19268 return (SrcBits == 64 && DestBits == 32);
19304 return Subtarget->hasFullFP16();
19311 if (!Subtarget->hasMVEIntegerOps())
19329 if (
auto *Ld = dyn_cast<MaskedLoadSDNode>(ExtVal.
getOperand(0))) {
19330 if (Ld->isExpandingLoad())
19334 if (Subtarget->hasMVEIntegerOps())
19379bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19381 if (Subtarget->useSoftFloat())
19390 return Subtarget->hasMVEFloatOps();
19408 unsigned Scale = 1;
19425 if ((V & (Scale - 1)) != 0)
19427 return isUInt<5>(V / Scale);
19434 if (VT.
isVector() && Subtarget->hasNEON())
19437 !Subtarget->hasMVEFloatOps())
19440 bool IsNeg =
false;
19446 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19449 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19453 return isShiftedUInt<7,2>(V);
19456 return isShiftedUInt<7,1>(V);
19458 return isUInt<7>(V);
19465 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19466 return isShiftedUInt<8, 1>(V);
19469 return isShiftedUInt<8, 2>(V);
19471 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19474 return isUInt<8>(V);
19475 return isUInt<12>(V);
19501 default:
return false;
19506 return isUInt<12>(V);
19509 return isUInt<8>(V);
19514 return isShiftedUInt<8, 2>(V);
19520 int Scale = AM.
Scale;
19525 default:
return false;
19533 Scale = Scale & ~1;
19534 return Scale == 2 || Scale == 4 || Scale == 8;
19551 if (Scale & 1)
return false;
19558 const int Scale = AM.
Scale;
19568 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
19584 switch (AM.
Scale) {
19601 int Scale = AM.
Scale;
19603 default:
return false;
19607 if (Scale < 0) Scale = -Scale;
19615 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
19628 if (Scale & 1)
return false;
19641 if (!Subtarget->isThumb())
19648 return Imm >= 0 && Imm <= 255;
19657 int64_t AbsImm = std::abs(Imm);
19658 if (!Subtarget->isThumb())
19663 return AbsImm >= 0 && AbsImm <= 255;
19698 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
19702 int RHSC = (int)
RHS->getZExtValue();
19703 if (RHSC < 0 && RHSC > -256) {
19713 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
19716 int RHSC = (int)
RHS->getZExtValue();
19717 if (RHSC < 0 && RHSC > -0x1000) {
19759 int RHSC = (int)
RHS->getZExtValue();
19760 if (RHSC < 0 && RHSC > -0x100) {
19765 }
else if (RHSC > 0 && RHSC < 0x100) {
19776 bool isSEXTLoad,
bool IsMasked,
bool isLE,
19781 if (!isa<ConstantSDNode>(
Ptr->getOperand(1)))
19787 bool CanChangeType = isLE && !IsMasked;
19790 int RHSC = (int)
RHS->getZExtValue();
19792 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
19793 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
19798 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
19809 if (VT == MVT::v4i16) {
19810 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
19812 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
19813 if (IsInRange(RHSC, 0x80, 1))
19815 }
else if (Alignment >= 4 &&
19816 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
19817 IsInRange(RHSC, 0x80, 4))
19819 else if (Alignment >= 2 &&
19820 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
19821 IsInRange(RHSC, 0x80, 2))
19823 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
19842 bool isSEXTLoad =
false;
19843 bool IsMasked =
false;
19845 Ptr = LD->getBasePtr();
19846 VT = LD->getMemoryVT();
19847 Alignment = LD->getAlign();
19849 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
19850 Ptr = ST->getBasePtr();
19851 VT = ST->getMemoryVT();
19852 Alignment = ST->getAlign();
19854 Ptr = LD->getBasePtr();
19855 VT = LD->getMemoryVT();
19856 Alignment = LD->getAlign();
19860 Ptr = ST->getBasePtr();
19861 VT = ST->getMemoryVT();
19862 Alignment = ST->getAlign();
19868 bool isLegal =
false;
19870 isLegal = Subtarget->hasMVEIntegerOps() &&
19872 Ptr.getNode(), VT, Alignment, isSEXTLoad, IsMasked,
19900 bool isSEXTLoad =
false, isNonExt;
19901 bool IsMasked =
false;
19903 VT = LD->getMemoryVT();
19904 Ptr = LD->getBasePtr();
19905 Alignment = LD->getAlign();
19908 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
19909 VT = ST->getMemoryVT();
19910 Ptr = ST->getBasePtr();
19911 Alignment = ST->getAlign();
19912 isNonExt = !ST->isTruncatingStore();
19914 VT = LD->getMemoryVT();
19915 Ptr = LD->getBasePtr();
19916 Alignment = LD->getAlign();
19921 VT = ST->getMemoryVT();
19922 Ptr = ST->getBasePtr();
19923 Alignment = ST->getAlign();
19924 isNonExt = !ST->isTruncatingStore();
19932 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
19933 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
19935 auto *
RHS = dyn_cast<ConstantSDNode>(
Op->getOperand(1));
19936 if (!
RHS ||
RHS->getZExtValue() != 4)
19938 if (Alignment <
Align(4))
19942 Base =
Op->getOperand(0);
19948 bool isLegal =
false;
19950 isLegal = Subtarget->hasMVEIntegerOps() &&
19983 const APInt &DemandedElts,
19985 unsigned Depth)
const {
19988 switch (
Op.getOpcode()) {
19995 if (
Op.getResNo() == 0) {
20021 case Intrinsic::arm_ldaex:
20022 case Intrinsic::arm_ldrex: {
20023 EVT VT = cast<MemIntrinsicSDNode>(
Op)->getMemoryVT();
20037 const APInt &Mask =
Op.getConstantOperandAPInt(2);
20038 Known.
Zero &= Mask;
20044 const SDValue &SrcSV =
Op.getOperand(0);
20050 "VGETLANE index out of bounds");
20055 EVT VT =
Op.getValueType();
20062 Known = Known.
sext(DstSz);
20064 Known = Known.
zext(DstSz);
20072 Known = KnownOp.
zext(32);
20112 EVT VT =
Op.getValueType();
20118 assert(VT == MVT::i32 &&
"Unexpected integer type");
20125 unsigned Mask =
C->getZExtValue();
20128 unsigned ShrunkMask = Mask & Demanded;
20129 unsigned ExpandedMask = Mask | ~Demanded;
20133 if (ShrunkMask == 0)
20139 if (ExpandedMask == ~0U)
20142 auto IsLegalMask = [ShrunkMask, ExpandedMask](
unsigned Mask) ->
bool {
20143 return (ShrunkMask & Mask) == ShrunkMask && (~ExpandedMask & Mask) == 0;
20145 auto UseMask = [Mask,
Op, VT, &TLO](
unsigned NewMask) ->
bool {
20146 if (NewMask == Mask)
20155 if (IsLegalMask(0xFF))
20156 return UseMask(0xFF);
20159 if (IsLegalMask(0xFFFF))
20160 return UseMask(0xFFFF);
20164 if (ShrunkMask < 256)
20165 return UseMask(ShrunkMask);
20169 if ((
int)ExpandedMask <= -2 && (
int)ExpandedMask >= -256)
20170 return UseMask(ExpandedMask);
20185 unsigned Depth)
const {
20186 unsigned Opc =
Op.getOpcode();
20194 if (
Op.getResNo() == 0 && !
Op->hasAnyUseOfValue(1) &&
20195 isa<ConstantSDNode>(
Op->getOperand(2))) {
20196 unsigned ShAmt =
Op->getConstantOperandVal(2);
20208 unsigned ModImm =
Op.getConstantOperandVal(1);
20209 unsigned EltBits = 0;
20211 if ((OriginalDemandedBits & Mask) == 0)
20217 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
20226 if (!Subtarget->hasV6Ops())
20232 SplitString(AsmStr, AsmPieces,
";\n");
20234 switch (AsmPieces.
size()) {
20235 default:
return false;
20237 AsmStr = AsmPieces[0];
20239 SplitString(AsmStr, AsmPieces,
" \t,");
20242 if (AsmPieces.
size() == 3 &&
20243 AsmPieces[0] ==
"rev" && AsmPieces[1] ==
"$0" && AsmPieces[2] ==
"$1" &&
20244 IA->getConstraintString().compare(0, 4,
"=l,l") == 0) {
20267 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20279 unsigned S = Constraint.
size();
20281 switch (Constraint[0]) {
20293 }
else if (S == 2) {
20294 switch (Constraint[0]) {
20311 Value *CallOperandVal =
info.CallOperandVal;
20314 if (!CallOperandVal)
20318 switch (*constraint) {
20324 if (Subtarget->isThumb())
20338using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20342 switch (Constraint.
size()) {
20345 switch (Constraint[0]) {
20347 if (Subtarget->isThumb())
20348 return RCPair(0U, &ARM::tGPRRegClass);
20349 return RCPair(0U, &ARM::GPRRegClass);
20351 if (Subtarget->isThumb())
20352 return RCPair(0U, &ARM::hGPRRegClass);
20356 return RCPair(0U, &ARM::tGPRRegClass);
20357 return RCPair(0U, &ARM::GPRRegClass);
20359 if (VT == MVT::Other)
20361 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20362 return RCPair(0U, &ARM::SPRRegClass);
20364 return RCPair(0U, &ARM::DPRRegClass);
20366 return RCPair(0U, &ARM::QPRRegClass);
20369 if (VT == MVT::Other)
20371 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20372 return RCPair(0U, &ARM::SPR_8RegClass);
20374 return RCPair(0U, &ARM::DPR_8RegClass);
20376 return RCPair(0U, &ARM::QPR_8RegClass);
20379 if (VT == MVT::Other)
20381 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20382 return RCPair(0U, &ARM::SPRRegClass);
20384 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20386 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20392 if (Constraint[0] ==
'T') {
20393 switch (Constraint[1]) {
20397 return RCPair(0U, &ARM::tGPREvenRegClass);
20399 return RCPair(0U, &ARM::tGPROddRegClass);
20408 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20409 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20418 std::vector<SDValue> &Ops,
20423 if (Constraint.
size() != 1)
20426 char ConstraintLetter = Constraint[0];
20427 switch (ConstraintLetter) {
20430 case 'I':
case 'J':
case 'K':
case 'L':
20431 case 'M':
case 'N':
case 'O':
20436 int64_t CVal64 =
C->getSExtValue();
20437 int CVal = (int) CVal64;
20440 if (CVal != CVal64)
20443 switch (ConstraintLetter) {
20447 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
20448 if (CVal >= 0 && CVal <= 65535)
20455 if (CVal >= 0 && CVal <= 255)
20457 }
else if (Subtarget->
isThumb2()) {
20476 if (CVal >= -255 && CVal <= -1)
20482 if (CVal >= -4095 && CVal <= 4095)
20495 }
else if (Subtarget->
isThumb2()) {
20518 if (CVal >= -7 && CVal < 7)
20520 }
else if (Subtarget->
isThumb2()) {
20543 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
20549 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
20557 if (CVal >= 0 && CVal <= 31)
20566 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
20575 if (Result.getNode()) {
20576 Ops.push_back(Result);
20586 "Unhandled Opcode in getDivRemLibcall");
20592 case MVT::i8: LC =
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
20593 case MVT::i16: LC =
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
20594 case MVT::i32: LC =
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
20595 case MVT::i64: LC =
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
20604 "Unhandled Opcode in getDivRemArgList");
20609 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
20610 EVT ArgVT =
N->getOperand(i).getValueType();
20612 Entry.Node =
N->getOperand(i);
20616 Args.push_back(Entry);
20627 "Register-based DivRem lowering only");
20628 unsigned Opcode =
Op->getOpcode();
20630 "Invalid opcode for Div/Rem lowering");
20632 EVT VT =
Op->getValueType(0);
20635 if (VT == MVT::i64 && isa<ConstantSDNode>(
Op.getOperand(1))) {
20654 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
20655 : Subtarget->hasDivideInARMMode();
20656 if (hasDivide &&
Op->getValueType(0).isSimple() &&
20657 Op->getSimpleValueType(0) == MVT::i32) {
20659 const SDValue Dividend =
Op->getOperand(0);
20660 const SDValue Divisor =
Op->getOperand(1);
20661 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
20665 SDValue Values[2] = {Div, Rem};
20697 EVT VT =
N->getValueType(0);
20699 if (VT == MVT::i64 && isa<ConstantSDNode>(
N->getOperand(1))) {
20703 Result[0], Result[1]);
20707 std::vector<Type*> RetTyParams;
20708 Type *RetTyElement;
20718 RetTyParams.push_back(RetTyElement);
20719 RetTyParams.push_back(RetTyElement);
20736 CallLoweringInfo CLI(DAG);
20740 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
20743 SDNode *ResNode = CallResult.first.getNode();
20758 "no-stack-arg-probe")) {
20760 cast<ConstantSDNode>(
Op.getOperand(2))->getMaybeAlignValue();
20769 SDValue Ops[2] = { SP, Chain };
20786 SDValue Ops[2] = { NewSP, Chain };
20791 bool IsStrict =
Op->isStrictFPOpcode();
20792 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20793 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20795 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
20796 "Unexpected type for custom-lowering FP_EXTEND");
20799 "With both FP DP and 16, any FP conversion is legal!");
20801 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
20802 "With FP16, 16 to 32 conversion is legal!");
20805 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
20810 Loc,
Op.getValueType(), SrcVal);
20823 MakeLibCallOptions CallOptions;
20825 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
20826 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
20827 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
20828 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
20832 {DstVT, MVT::Other}, {Chain, SrcVal});
20839 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20840 "Unexpected type for custom-lowering FP_EXTEND");
20841 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20846 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
20850 bool IsStrict =
Op->isStrictFPOpcode();
20852 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20854 EVT DstVT =
Op.getValueType();
20855 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20858 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
20859 "Unexpected type for custom-lowering FP_ROUND");
20862 "With both FP DP and 16, any FP conversion is legal!");
20867 if (SrcSz == 32 && Subtarget->hasFP16())
20872 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20873 "Unexpected type for custom-lowering FP_ROUND");
20874 MakeLibCallOptions CallOptions;
20877 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20889 if (v == 0xffffffff)
20901 bool ForCodeSize)
const {
20904 if (VT == MVT::f16 && Subtarget->hasFullFP16())
20906 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
20909 if (VT == MVT::f32)
20911 if (VT == MVT::f64 && Subtarget->hasFP64())
20922 unsigned Intrinsic)
const {
20923 switch (Intrinsic) {
20924 case Intrinsic::arm_neon_vld1:
20925 case Intrinsic::arm_neon_vld2:
20926 case Intrinsic::arm_neon_vld3:
20927 case Intrinsic::arm_neon_vld4:
20928 case Intrinsic::arm_neon_vld2lane:
20929 case Intrinsic::arm_neon_vld3lane:
20930 case Intrinsic::arm_neon_vld4lane:
20931 case Intrinsic::arm_neon_vld2dup:
20932 case Intrinsic::arm_neon_vld3dup:
20933 case Intrinsic::arm_neon_vld4dup: {
20936 auto &
DL =
I.getDataLayout();
20937 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20939 Info.ptrVal =
I.getArgOperand(0);
20941 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20942 Info.align = cast<ConstantInt>(AlignArg)->getMaybeAlignValue();
20947 case Intrinsic::arm_neon_vld1x2:
20948 case Intrinsic::arm_neon_vld1x3:
20949 case Intrinsic::arm_neon_vld1x4: {
20952 auto &
DL =
I.getDataLayout();
20953 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
20955 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
20957 Info.align =
I.getParamAlign(
I.arg_size() - 1).valueOrOne();
20962 case Intrinsic::arm_neon_vst1:
20963 case Intrinsic::arm_neon_vst2:
20964 case Intrinsic::arm_neon_vst3:
20965 case Intrinsic::arm_neon_vst4:
20966 case Intrinsic::arm_neon_vst2lane:
20967 case Intrinsic::arm_neon_vst3lane:
20968 case Intrinsic::arm_neon_vst4lane: {
20971 auto &
DL =
I.getDataLayout();
20972 unsigned NumElts = 0;
20973 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20974 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20977 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
20980 Info.ptrVal =
I.getArgOperand(0);
20982 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
20983 Info.align = cast<ConstantInt>(AlignArg)->getMaybeAlignValue();
20988 case Intrinsic::arm_neon_vst1x2:
20989 case Intrinsic::arm_neon_vst1x3:
20990 case Intrinsic::arm_neon_vst1x4: {
20993 auto &
DL =
I.getDataLayout();
20994 unsigned NumElts = 0;
20995 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
20996 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
20999 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21002 Info.ptrVal =
I.getArgOperand(0);
21004 Info.align =
I.getParamAlign(0).valueOrOne();
21009 case Intrinsic::arm_mve_vld2q:
21010 case Intrinsic::arm_mve_vld4q: {
21013 Type *VecTy = cast<StructType>(
I.getType())->getElementType(1);
21014 unsigned Factor = Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
21016 Info.ptrVal =
I.getArgOperand(0);
21023 case Intrinsic::arm_mve_vst2q:
21024 case Intrinsic::arm_mve_vst4q: {
21027 Type *VecTy =
I.getArgOperand(1)->getType();
21028 unsigned Factor = Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
21030 Info.ptrVal =
I.getArgOperand(0);
21037 case Intrinsic::arm_mve_vldr_gather_base:
21038 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
21040 Info.ptrVal =
nullptr;
21046 case Intrinsic::arm_mve_vldr_gather_base_wb:
21047 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
21049 Info.ptrVal =
nullptr;
21055 case Intrinsic::arm_mve_vldr_gather_offset:
21056 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
21058 Info.ptrVal =
nullptr;
21060 unsigned MemSize = cast<ConstantInt>(
I.getArgOperand(2))->getZExtValue();
21067 case Intrinsic::arm_mve_vstr_scatter_base:
21068 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
21070 Info.ptrVal =
nullptr;
21076 case Intrinsic::arm_mve_vstr_scatter_base_wb:
21077 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
21079 Info.ptrVal =
nullptr;
21085 case Intrinsic::arm_mve_vstr_scatter_offset:
21086 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
21088 Info.ptrVal =
nullptr;
21090 unsigned MemSize = cast<ConstantInt>(
I.getArgOperand(3))->getZExtValue();
21097 case Intrinsic::arm_ldaex:
21098 case Intrinsic::arm_ldrex: {
21099 auto &
DL =
I.getDataLayout();
21100 Type *ValTy =
I.getParamElementType(0);
21103 Info.ptrVal =
I.getArgOperand(0);
21105 Info.align =
DL.getABITypeAlign(ValTy);
21109 case Intrinsic::arm_stlex:
21110 case Intrinsic::arm_strex: {
21111 auto &
DL =
I.getDataLayout();
21112 Type *ValTy =
I.getParamElementType(1);
21115 Info.ptrVal =
I.getArgOperand(1);
21117 Info.align =
DL.getABITypeAlign(ValTy);
21121 case Intrinsic::arm_stlexd:
21122 case Intrinsic::arm_strexd:
21124 Info.memVT = MVT::i64;
21125 Info.ptrVal =
I.getArgOperand(2);
21131 case Intrinsic::arm_ldaexd:
21132 case Intrinsic::arm_ldrexd:
21134 Info.memVT = MVT::i64;
21135 Info.ptrVal =
I.getArgOperand(0);
21155 if (Bits == 0 || Bits > 32)
21161 unsigned Index)
const {
21171 if (!Subtarget->hasDataBarrier()) {
21175 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
21210 if (Subtarget->preferISHSTBarriers())
21243 bool has64BitAtomicStore;
21245 has64BitAtomicStore =
false;
21246 else if (Subtarget->isThumb())
21247 has64BitAtomicStore = Subtarget->hasV7Ops();
21249 has64BitAtomicStore = Subtarget->hasV6Ops();
21251 unsigned Size = SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21265 bool has64BitAtomicLoad;
21267 has64BitAtomicLoad =
false;
21268 else if (Subtarget->isThumb())
21269 has64BitAtomicLoad = Subtarget->hasV7Ops();
21271 has64BitAtomicLoad = Subtarget->hasV6Ops();
21288 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21289 else if (Subtarget->isThumb())
21290 hasAtomicRMW = Subtarget->hasV7Ops();
21292 hasAtomicRMW = Subtarget->hasV6Ops();
21293 if (
Size <= (Subtarget->
isMClass() ? 32U : 64U) && hasAtomicRMW) {
21316 bool HasAtomicCmpXchg;
21318 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21319 else if (Subtarget->isThumb())
21320 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21322 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21324 HasAtomicCmpXchg &&
Size <= (Subtarget->
isMClass() ? 32U : 64U))
21331 return InsertFencesForAtomic;
21344 M.getOrInsertGlobal(
"__security_cookie",
21352 F->addParamAttr(0, Attribute::AttrKind::InReg);
21358 return M.getGlobalVariable(
"__security_cookie");
21365 return M.getFunction(
"__security_check_cookie");
21370 unsigned &
Cost)
const {
21372 if (!Subtarget->hasNEON())
21384 if (!isa<ConstantInt>(
Idx))
21399 return Subtarget->hasV6T2Ops();
21403 return Subtarget->hasV6T2Ops();
21408 if (!Subtarget->hasV7Ops())
21414 if (!Mask || Mask->getValue().getBitWidth() > 32u)
21416 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
21441 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
21453 Lo, Builder.
CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
21456 Type *Tys[] = {
Addr->getType() };
21457 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
21461 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
21467 if (!Subtarget->hasV7Ops())
21483 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
21493 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
21494 Type *Tys[] = {
Addr->getType() };
21516 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
21523 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
21526 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
21534 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
21542 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
21545 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
21550 if (Subtarget->hasNEON() && VecSize == 64)
21552 return VecSize % 128 == 0;
21556 if (Subtarget->hasNEON())
21558 if (Subtarget->hasMVEIntegerOps())
21578 "Invalid interleave factor");
21579 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
21581 "Unmatched number of shufflevectors and indices");
21583 auto *VecTy = cast<FixedVectorType>(Shuffles[0]->
getType());
21584 Type *EltTy = VecTy->getElementType();
21607 if (NumLoads > 1) {
21611 VecTy->getNumElements() / NumLoads);
21616 auto createLoadIntrinsic = [&](
Value *BaseAddr) {
21617 if (Subtarget->hasNEON()) {
21619 Type *Tys[] = {VecTy, PtrTy};
21620 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
21621 Intrinsic::arm_neon_vld3,
21622 Intrinsic::arm_neon_vld4};
21631 assert((Factor == 2 || Factor == 4) &&
21632 "expected interleave factor of 2 or 4 for MVE");
21634 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
21636 Type *Tys[] = {VecTy, PtrTy};
21650 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
21655 VecTy->getNumElements() * Factor);
21657 CallInst *VldN = createLoadIntrinsic(BaseAddr);
21661 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
21663 unsigned Index = Indices[i];
21673 SubVecs[SV].push_back(SubVec);
21682 auto &SubVec = SubVecs[SVI];
21685 SVI->replaceAllUsesWith(WideVec);
21719 unsigned Factor)
const {
21721 "Invalid interleave factor");
21723 auto *VecTy = cast<FixedVectorType>(SVI->
getType());
21724 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
21726 unsigned LaneLen = VecTy->getNumElements() / Factor;
21727 Type *EltTy = VecTy->getElementType();
21731 Align Alignment = SI->getAlign();
21748 Type *IntTy =
DL.getIntPtrType(EltTy);
21760 Value *BaseAddr = SI->getPointerOperand();
21762 if (NumStores > 1) {
21765 LaneLen /= NumStores;
21773 auto createStoreIntrinsic = [&](
Value *BaseAddr,
21775 if (Subtarget->hasNEON()) {
21776 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
21777 Intrinsic::arm_neon_vst3,
21778 Intrinsic::arm_neon_vst4};
21779 Type *PtrTy = Builder.
getPtrTy(SI->getPointerAddressSpace());
21780 Type *Tys[] = {PtrTy, SubVecTy};
21788 assert((Factor == 2 || Factor == 4) &&
21789 "expected interleave factor of 2 or 4 for MVE");
21791 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
21792 Type *PtrTy = Builder.
getPtrTy(SI->getPointerAddressSpace());
21793 Type *Tys[] = {PtrTy, SubVecTy};
21798 for (
unsigned F = 0;
F < Factor;
F++) {
21806 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
21809 if (StoreCount > 0)
21811 BaseAddr, LaneLen * Factor);
21816 for (
unsigned i = 0; i < Factor; i++) {
21817 unsigned IdxI = StoreCount * LaneLen * Factor + i;
21818 if (Mask[IdxI] >= 0) {
21822 unsigned StartMask = 0;
21823 for (
unsigned j = 1; j < LaneLen; j++) {
21824 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
21825 if (Mask[IdxJ * Factor + IdxI] >= 0) {
21826 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
21841 createStoreIntrinsic(BaseAddr, Shuffles);
21856 if (
auto *ST = dyn_cast<StructType>(Ty)) {
21857 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
21861 Members += SubMembers;
21863 }
else if (
auto *AT = dyn_cast<ArrayType>(Ty)) {
21867 Members += SubMembers * AT->getNumElements();
21878 }
else if (
auto *VT = dyn_cast<VectorType>(Ty)) {
21885 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
21887 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
21889 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
21902 return (Members > 0 && Members <= 4);
21908 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
21910 return ABITypeAlign;
21915 assert(StackAlign &&
"data layout string is missing stack alignment");
21916 return std::min(ABITypeAlign, *StackAlign);
21925 if (getEffectiveCallingConv(CallConv, isVarArg) !=
21935 return IsHA || IsIntArray;
21939 const Constant *PersonalityFn)
const {
21946 const Constant *PersonalityFn)
const {
21958void ARMTargetLowering::insertCopiesSplitCSR(
21962 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
21972 RC = &ARM::GPRRegClass;
21973 else if (ARM::DPRRegClass.
contains(*
I))
21974 RC = &ARM::DPRRegClass;
21984 assert(Entry->getParent()->getFunction().hasFnAttribute(
21985 Attribute::NoUnwind) &&
21986 "Function should be nounwind in insertCopiesSplitCSR!");
21987 Entry->addLiveIn(*
I);
21992 for (
auto *Exit : Exits)
21994 TII->get(TargetOpcode::COPY), *
I)
22005 return Subtarget->hasMVEIntegerOps();
22010 auto *VTy = dyn_cast<FixedVectorType>(Ty);
22015 unsigned NumElements = VTy->getNumElements();
22022 if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy())
22023 return Subtarget->hasMVEFloatOps();
22028 return Subtarget->hasMVEIntegerOps() &&
22029 (ScalarTy->isIntegerTy(8) || ScalarTy->isIntegerTy(16) ||
22030 ScalarTy->isIntegerTy(32));
22042 assert(TyWidth >= 128 &&
"Width of vector type must be at least 128 bits");
22044 if (TyWidth > 128) {
22049 ArrayRef<int> UpperSplitMask(&SplitSeqVec[Stride], Stride);
22051 auto *LowerSplitA =
B.CreateShuffleVector(InputA, LowerSplitMask);
22052 auto *LowerSplitB =
B.CreateShuffleVector(InputB, LowerSplitMask);
22053 auto *UpperSplitA =
B.CreateShuffleVector(InputA, UpperSplitMask);
22054 auto *UpperSplitB =
B.CreateShuffleVector(InputB, UpperSplitMask);
22055 Value *LowerSplitAcc =
nullptr;
22056 Value *UpperSplitAcc =
nullptr;
22059 LowerSplitAcc =
B.CreateShuffleVector(
Accumulator, LowerSplitMask);
22060 UpperSplitAcc =
B.CreateShuffleVector(
Accumulator, UpperSplitMask);
22064 B, OperationType, Rotation, LowerSplitA, LowerSplitB, LowerSplitAcc);
22066 B, OperationType, Rotation, UpperSplitA, UpperSplitB, UpperSplitAcc);
22069 return B.CreateShuffleVector(LowerSplitInt, UpperSplitInt, JoinMask);
22076 ConstRotation = ConstantInt::get(IntTy, (
int)Rotation);
22079 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmlaq, Ty,
22081 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmulq, Ty,
22082 {ConstRotation, InputB, InputA});
22087 auto *ConstHalving = ConstantInt::get(IntTy, 1);
22090 ConstRotation = ConstantInt::get(IntTy, 0);
22092 ConstRotation = ConstantInt::get(IntTy, 1);
22094 if (!ConstRotation)
22097 return B.CreateIntrinsic(Intrinsic::arm_mve_vcaddq, Ty,
22098 {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)