84#include "llvm/IR/IntrinsicsARM.h"
122#define DEBUG_TYPE "arm-isel"
125STATISTIC(NumMovwMovt,
"Number of GAs materialized with movw + movt");
126STATISTIC(NumLoopByVals,
"Number of loops generated for byval arguments");
128 "Number of constants with their storage promoted into constant pools");
132 cl::desc(
"Enable / disable ARM interworking (for debugging only)"),
137 cl::desc(
"Enable / disable promotion of unnamed_addr constants into "
142 cl::desc(
"Maximum size of constant to promote into a constant pool"),
146 cl::desc(
"Maximum size of ALL constants to promote into a constant pool"),
151 cl::desc(
"Maximum interleave factor for MVE VLDn to generate."),
156 ARM::R0, ARM::R1, ARM::R2, ARM::R3
170void ARMTargetLowering::addTypeForNEON(
MVT VT,
MVT PromotedLdStVT) {
171 if (VT != PromotedLdStVT) {
180 if (ElemTy != MVT::f64)
184 if (ElemTy == MVT::i32) {
228void ARMTargetLowering::addDRTypeForNEON(
MVT VT) {
230 addTypeForNEON(VT, MVT::f64);
233void ARMTargetLowering::addQRTypeForNEON(
MVT VT) {
235 addTypeForNEON(VT, MVT::v2f64);
238void ARMTargetLowering::setAllExpand(
MVT VT) {
251void ARMTargetLowering::addAllExtLoads(
const MVT From,
const MVT To,
252 LegalizeAction Action) {
258void ARMTargetLowering::addMVEVectorTypes(
bool HasMVEFP) {
259 const MVT IntTypes[] = { MVT::v16i8, MVT::v8i16, MVT::v4i32 };
261 for (
auto VT : IntTypes) {
335 const MVT FloatTypes[] = { MVT::v8f16, MVT::v4f32 };
336 for (
auto VT : FloatTypes) {
405 const MVT LongTypes[] = { MVT::v2i64, MVT::v2f64 };
406 for (
auto VT : LongTypes) {
423 addAllExtLoads(MVT::v8i16, MVT::v8i8,
Legal);
424 addAllExtLoads(MVT::v4i32, MVT::v4i16,
Legal);
425 addAllExtLoads(MVT::v4i32, MVT::v4i8,
Legal);
442 for (
auto VT : {MVT::v8i8, MVT::v4i8, MVT::v4i16}) {
451 const MVT pTypes[] = {MVT::v16i1, MVT::v8i1, MVT::v4i1, MVT::v2i1};
452 for (
auto VT : pTypes) {
508 for (
int LCID = 0; LCID < RTLIB::UNKNOWN_LIBCALL; ++LCID)
516 if (Subtarget->isThumb() && Subtarget->
hasVFP2Base() &&
517 Subtarget->
hasARMOps() && !Subtarget->useSoftFloat()) {
518 static const struct {
520 const char *
const Name;
542 { RTLIB::UO_F32,
"__unordsf2vfp",
ISD::SETNE },
551 { RTLIB::UO_F64,
"__unorddf2vfp",
ISD::SETNE },
576 for (
const auto &LC : LibraryCalls) {
588 static const struct {
590 const char *
const Name;
675 for (
const auto &LC : LibraryCalls) {
685 static const struct {
687 const char *
const Name;
690 } MemOpsLibraryCalls[] = {
698 for (
const auto &LC : MemOpsLibraryCalls) {
708 static const struct {
710 const char *
const Name;
723 for (
const auto &LC : LibraryCalls) {
755 static const struct {
757 const char *
const Name;
765 for (
const auto &LC : LibraryCalls) {
776 if (!Subtarget->useSoftFloat() && !Subtarget->
isThumb1Only() &&
777 Subtarget->hasFPRegs()) {
787 setAllExpand(MVT::f32);
788 if (!Subtarget->hasFP64())
789 setAllExpand(MVT::f64);
792 if (Subtarget->hasFullFP16()) {
801 if (Subtarget->hasBF16()) {
803 setAllExpand(MVT::bf16);
804 if (!Subtarget->hasFullFP16())
811 addAllExtLoads(VT, InnerVT,
Expand);
826 if (Subtarget->hasMVEIntegerOps())
827 addMVEVectorTypes(Subtarget->hasMVEFloatOps());
830 if (Subtarget->hasLOB()) {
834 if (Subtarget->hasNEON()) {
835 addDRTypeForNEON(MVT::v2f32);
836 addDRTypeForNEON(MVT::v8i8);
837 addDRTypeForNEON(MVT::v4i16);
838 addDRTypeForNEON(MVT::v2i32);
839 addDRTypeForNEON(MVT::v1i64);
841 addQRTypeForNEON(MVT::v4f32);
842 addQRTypeForNEON(MVT::v2f64);
843 addQRTypeForNEON(MVT::v16i8);
844 addQRTypeForNEON(MVT::v8i16);
845 addQRTypeForNEON(MVT::v4i32);
846 addQRTypeForNEON(MVT::v2i64);
848 if (Subtarget->hasFullFP16()) {
849 addQRTypeForNEON(MVT::v8f16);
850 addDRTypeForNEON(MVT::v4f16);
853 if (Subtarget->hasBF16()) {
854 addQRTypeForNEON(MVT::v8bf16);
855 addDRTypeForNEON(MVT::v4bf16);
859 if (Subtarget->hasMVEIntegerOps() || Subtarget->hasNEON()) {
899 if (Subtarget->hasNEON()) {
1013 for (
MVT Ty : {MVT::v8i8, MVT::v4i8, MVT::v2i8, MVT::v4i16, MVT::v2i16,
1022 for (
auto VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32, MVT::v16i8, MVT::v8i16,
1031 if (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) {
1039 if (Subtarget->hasMVEIntegerOps()) {
1044 if (Subtarget->hasMVEFloatOps()) {
1048 if (!Subtarget->hasFP64()) {
1095 if (Subtarget->hasFullFP16()) {
1101 if (!Subtarget->hasFP16()) {
1149 if (Subtarget->hasDSP()) {
1171 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6Ops()
1172 || (Subtarget->
isThumb2() && !Subtarget->hasDSP()))
1187 if (Subtarget->hasMVEIntegerOps())
1197 if (!Subtarget->
isThumb1Only() && Subtarget->hasV6T2Ops())
1208 if (!Subtarget->hasV5TOps() || Subtarget->
isThumb1Only()) {
1217 if (Subtarget->hasPerfMon())
1221 if (!Subtarget->hasV6Ops())
1224 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
1225 : Subtarget->hasDivideInARMMode();
1232 if (Subtarget->
isTargetWindows() && !Subtarget->hasDivideInThumbMode()) {
1249 HasStandaloneRem =
false;
1254 const char *
const Name;
1256 } LibraryCalls[] = {
1268 for (
const auto &LC : LibraryCalls) {
1275 const char *
const Name;
1277 } LibraryCalls[] = {
1289 for (
const auto &LC : LibraryCalls) {
1327 InsertFencesForAtomic =
false;
1329 (!Subtarget->isThumb() || Subtarget->hasV8MBaselineOps())) {
1333 if (!Subtarget->isThumb() || !Subtarget->
isMClass())
1338 if (!Subtarget->hasAcquireRelease() ||
1341 InsertFencesForAtomic =
true;
1347 if (Subtarget->hasDataBarrier())
1348 InsertFencesForAtomic =
true;
1368 if (!InsertFencesForAtomic) {
1376 (!Subtarget->
isMClass() && Subtarget->hasV6Ops())) {
1388 }
else if ((Subtarget->
isMClass() && Subtarget->hasV8MBaselineOps()) ||
1389 Subtarget->hasForced32BitAtomics()) {
1403 if (!Subtarget->hasV6Ops()) {
1409 if (!Subtarget->useSoftFloat() && Subtarget->hasFPRegs() &&
1441 if (Subtarget->hasFullFP16()) {
1451 if (Subtarget->hasFullFP16())
1466 if (!Subtarget->useSoftFloat() && Subtarget->
hasVFP2Base() &&
1480 if (!Subtarget->useSoftFloat() && !Subtarget->
isThumb1Only()) {
1488 if (!Subtarget->hasFP16()) {
1519 if (Subtarget->hasNEON()) {
1526 if (Subtarget->hasFP64()) {
1539 if (Subtarget->hasFullFP16()) {
1558 if (Subtarget->hasNEON()) {
1570 if (Subtarget->hasFullFP16()) {
1602 if (Subtarget->hasMVEIntegerOps())
1605 if (Subtarget->hasV6Ops())
1610 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) ||
1617 if (Subtarget->useSoftFloat() || Subtarget->
isThumb1Only() ||
1645 return Subtarget->useSoftFloat();
1658std::pair<const TargetRegisterClass *, uint8_t>
1669 case MVT::f32:
case MVT::f64:
case MVT::v8i8:
case MVT::v4i16:
1670 case MVT::v2i32:
case MVT::v1i64:
case MVT::v2f32:
1671 RRC = &ARM::DPRRegClass;
1679 case MVT::v16i8:
case MVT::v8i16:
case MVT::v4i32:
case MVT::v2i64:
1680 case MVT::v4f32:
case MVT::v2f64:
1681 RRC = &ARM::DPRRegClass;
1685 RRC = &ARM::DPRRegClass;
1689 RRC = &ARM::DPRRegClass;
1693 return std::make_pair(RRC,
Cost);
1697#define MAKE_CASE(V) \
1916 if ((Subtarget->hasMVEIntegerOps() &&
1917 (VT == MVT::v2i64 || VT == MVT::v4i32 || VT == MVT::v8i16 ||
1918 VT == MVT::v16i8)) ||
1919 (Subtarget->hasMVEFloatOps() &&
1920 (VT == MVT::v2f64 || VT == MVT::v4f32 || VT == MVT::v8f16)))
1934 if (Subtarget->hasNEON()) {
1935 if (VT == MVT::v4i64)
1936 return &ARM::QQPRRegClass;
1937 if (VT == MVT::v8i64)
1938 return &ARM::QQQQPRRegClass;
1940 if (Subtarget->hasMVEIntegerOps()) {
1941 if (VT == MVT::v4i64)
1942 return &ARM::MQQPRRegClass;
1943 if (VT == MVT::v8i64)
1944 return &ARM::MQQQQPRRegClass;
1953 Align &PrefAlign)
const {
1954 if (!isa<MemIntrinsic>(CI))
1972 unsigned NumVals =
N->getNumValues();
1976 for (
unsigned i = 0; i != NumVals; ++i) {
1977 EVT VT =
N->getValueType(i);
1978 if (VT == MVT::Glue || VT == MVT::Other)
1984 if (!
N->isMachineOpcode())
2008 if (
auto Const = dyn_cast<ConstantSDNode>(
Op.getOperand(1)))
2009 return Const->getZExtValue() == 16;
2016 if (
auto Const = dyn_cast<ConstantSDNode>(
Op.getOperand(1)))
2017 return Const->getZExtValue() == 16;
2024 if (
auto Const = dyn_cast<ConstantSDNode>(
Op.getOperand(1)))
2025 return Const->getZExtValue() == 16;
2094 bool isVarArg)
const {
2115 else if (Subtarget->hasFPRegs() && !Subtarget->
isThumb1Only() &&
2136 bool isVarArg)
const {
2137 return CCAssignFnForNode(
CC,
false, isVarArg);
2141 bool isVarArg)
const {
2142 return CCAssignFnForNode(
CC,
true, isVarArg);
2149 bool isVarArg)
const {
2150 switch (getEffectiveCallingConv(
CC, isVarArg)) {
2176 if (Subtarget->hasFullFP16()) {
2189 if (Subtarget->hasFullFP16()) {
2203SDValue ARMTargetLowering::LowerCallResult(
2207 SDValue ThisVal,
bool isCmseNSCall)
const {
2215 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
2220 if (i == 0 && isThisReturn) {
2222 "unexpected return calling convention register assignment");
2233 Chain =
Lo.getValue(1);
2234 InGlue =
Lo.getValue(2);
2238 Chain =
Hi.getValue(1);
2239 InGlue =
Hi.getValue(2);
2251 Chain =
Lo.getValue(1);
2252 InGlue =
Lo.getValue(2);
2255 Chain =
Hi.getValue(1);
2256 InGlue =
Hi.getValue(2);
2300std::pair<SDValue, MachinePointerInfo> ARMTargetLowering::computeAddrForCallArg(
2302 bool IsTailCall,
int SPDiff)
const {
2324 return std::make_pair(DstAddr, DstInfo);
2329 RegsToPassVector &RegsToPass,
2336 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
2337 unsigned id = Subtarget->
isLittle() ? 0 : 1;
2350 std::tie(DstAddr, DstInfo) =
2351 computeAddrForCallArg(dl, DAG, NextVA, StackPtr, IsTailCall, SPDiff);
2383 bool isStructRet = (Outs.
empty()) ?
false : Outs[0].
Flags.isSRet();
2384 bool isThisReturn =
false;
2385 bool isCmseNSCall =
false;
2386 bool isSibCall =
false;
2387 bool PreferIndirect =
false;
2388 bool GuardWithBTI =
false;
2398 !Subtarget->noBTIAtReturnTwice())
2403 isCmseNSCall =
true;
2415 if (isa<GlobalAddressSDNode>(Callee)) {
2419 auto *GV = cast<GlobalAddressSDNode>(Callee)->getGlobal();
2422 PreferIndirect = Subtarget->isThumb() && Subtarget->
hasMinSize() &&
2424 return isa<Instruction>(U) &&
2425 cast<Instruction>(U)->getParent() == BB;
2432 IsEligibleForTailCallOptimization(CLI, CCInfo, ArgLocs, PreferIndirect);
2446 "site marked musttail");
2449 unsigned NumBytes = CCInfo.getStackSize();
2458 if (isTailCall && !isSibCall) {
2465 NumBytes =
alignTo(NumBytes, StackAlign);
2470 SPDiff = NumReusableBytes - NumBytes;
2474 if (SPDiff < 0 && AFI->getArgRegsSaveSize() < (
unsigned)-SPDiff)
2490 RegsToPassVector RegsToPass;
2498 bool AfterFormalArgLoads =
false;
2502 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.
size();
2504 ++i, ++realArgIdx) {
2506 SDValue Arg = OutVals[realArgIdx];
2508 bool isByVal =
Flags.isByVal();
2528 if (isTailCall && VA.
isMemLoc() && !AfterFormalArgLoads) {
2530 AfterFormalArgLoads =
true;
2542 auto ArgVT = Outs[realArgIdx].ArgVT;
2543 if (isCmseNSCall && (ArgVT == MVT::f16)) {
2561 PassF64ArgInRegs(dl, DAG, Chain, Op0, RegsToPass, VA, ArgLocs[++i],
2562 StackPtr, MemOpChains, isTailCall, SPDiff);
2566 PassF64ArgInRegs(dl, DAG, Chain, Op1, RegsToPass, VA, ArgLocs[++i],
2567 StackPtr, MemOpChains, isTailCall, SPDiff);
2572 std::tie(DstAddr, DstInfo) =
2573 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2577 PassF64ArgInRegs(dl, DAG, Chain, Arg, RegsToPass, VA, ArgLocs[++i],
2578 StackPtr, MemOpChains, isTailCall, SPDiff);
2580 if (realArgIdx == 0 &&
Flags.isReturned() && !
Flags.isSwiftSelf() &&
2581 Outs[0].VT == MVT::i32) {
2583 "unexpected calling convention register assignment");
2584 assert(!
Ins.empty() && Ins[0].VT == MVT::i32 &&
2585 "unexpected use of 'returned'");
2586 isThisReturn =
true;
2590 CSInfo.ArgRegPairs.emplace_back(VA.
getLocReg(), i);
2591 RegsToPass.push_back(std::make_pair(VA.
getLocReg(), Arg));
2592 }
else if (isByVal) {
2594 unsigned offset = 0;
2598 unsigned ByValArgsCount = CCInfo.getInRegsParamsCount();
2599 unsigned CurByValIdx = CCInfo.getInRegsParamsProcessed();
2601 if (CurByValIdx < ByValArgsCount) {
2603 unsigned RegBegin, RegEnd;
2604 CCInfo.getInRegsParamInfo(CurByValIdx, RegBegin, RegEnd);
2609 for (i = 0, j = RegBegin;
j < RegEnd; i++,
j++) {
2616 RegsToPass.push_back(std::make_pair(j, Load));
2621 offset = RegEnd - RegBegin;
2623 CCInfo.nextInRegsParam();
2626 if (
Flags.getByValSize() > 4*offset) {
2630 std::tie(Dst, DstInfo) =
2631 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2640 SDValue Ops[] = { Chain, Dst, Src, SizeNode, AlignNode};
2648 std::tie(DstAddr, DstInfo) =
2649 computeAddrForCallArg(dl, DAG, VA, StackPtr, isTailCall, SPDiff);
2656 if (!MemOpChains.
empty())
2662 for (
unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
2663 Chain = DAG.
getCopyToReg(Chain, dl, RegsToPass[i].first,
2664 RegsToPass[i].second, InGlue);
2671 bool isDirect =
false;
2676 GVal =
G->getGlobal();
2677 bool isStub = !
TM.shouldAssumeDSOLocal(GVal) && Subtarget->
isTargetMachO();
2679 bool isARMFunc = !Subtarget->isThumb() || (isStub && !Subtarget->
isMClass());
2680 bool isLocalARMFunc =
false;
2683 if (Subtarget->genLongCalls()) {
2685 "long-calls codegen is not position independent!");
2689 if (isa<GlobalAddressSDNode>(Callee)) {
2690 if (Subtarget->genExecuteOnly()) {
2709 const char *
Sym = S->getSymbol();
2711 if (Subtarget->genExecuteOnly()) {
2730 }
else if (isa<GlobalAddressSDNode>(Callee)) {
2731 if (!PreferIndirect) {
2736 isLocalARMFunc = !Subtarget->isThumb() && (isDef || !
ARMInterworking);
2738 if (isStub && Subtarget->
isThumb1Only() && !Subtarget->hasV5TOps()) {
2750 "Windows is the only supported COFF target");
2754 else if (!
TM.shouldAssumeDSOLocal(GVal))
2770 const char *
Sym = S->getSymbol();
2771 if (isARMFunc && Subtarget->
isThumb1Only() && !Subtarget->hasV5TOps()) {
2775 ARMPCLabelIndex, 4);
2789 assert(!isARMFunc && !isDirect &&
2790 "Cannot handle call to ARM function or direct call");
2793 "call to non-secure function would "
2794 "require passing arguments on stack",
2801 "call to non-secure function would return value through pointer",
2809 if (Subtarget->isThumb()) {
2812 else if (isCmseNSCall)
2814 else if ((!isDirect || isARMFunc) && !Subtarget->hasV5TOps())
2819 if (!isDirect && !Subtarget->hasV5TOps())
2821 else if (doesNotRet && isDirect && Subtarget->hasRetAddrStack() &&
2834 if (isTailCall && !isSibCall) {
2839 std::vector<SDValue> Ops;
2840 Ops.push_back(Chain);
2841 Ops.push_back(Callee);
2850 for (
unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
2851 Ops.push_back(DAG.
getRegister(RegsToPass[i].first,
2852 RegsToPass[i].second.getValueType()));
2864 isThisReturn =
false;
2870 assert(Mask &&
"Missing call preserved mask for calling convention");
2874 Ops.push_back(InGlue);
2886 Chain = DAG.
getNode(CallOpc, dl, NodeTys, Ops);
2898 Chain = DAG.
getCALLSEQ_END(Chain, NumBytes, CalleePopBytes, InGlue, dl);
2904 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, dl, DAG,
2905 InVals, isThisReturn,
2906 isThisReturn ? OutVals[0] :
SDValue(), isCmseNSCall);
2913void ARMTargetLowering::HandleByVal(
CCState *State,
unsigned &
Size,
2914 Align Alignment)
const {
2916 Alignment = std::max(Alignment,
Align(4));
2922 unsigned AlignInRegs = Alignment.
value() / 4;
2923 unsigned Waste = (ARM::R4 -
Reg) % AlignInRegs;
2924 for (
unsigned i = 0; i < Waste; ++i)
2930 unsigned Excess = 4 * (ARM::R4 -
Reg);
2937 if (NSAAOffset != 0 &&
Size > Excess) {
2949 unsigned ByValRegBegin =
Reg;
2950 unsigned ByValRegEnd = std::min<unsigned>(Reg +
Size / 4, ARM::R4);
2954 for (
unsigned i = Reg + 1; i != ByValRegEnd; ++i)
2960 Size = std::max<int>(
Size - Excess, 0);
2971 int FI = std::numeric_limits<int>::max();
2979 if (!Flags.isByVal()) {
2985 }
else if (
LoadSDNode *Ld = dyn_cast<LoadSDNode>(Arg)) {
2986 if (Flags.isByVal())
3001 assert(FI != std::numeric_limits<int>::max());
3012bool ARMTargetLowering::IsEligibleForTailCallOptimization(
3038 if (!isa<GlobalAddressSDNode>(
Callee.getNode()) || isIndirect) {
3040 for (
Register R : {ARM::R0, ARM::R1, ARM::R2, ARM::R3})
3041 AddressRegisters.
insert(R);
3044 AddressRegisters.
insert(ARM::R12);
3047 AddressRegisters.
erase(
AL.getLocReg());
3048 if (AddressRegisters.
empty())
3062 return CalleeCC == CallerCC;
3066 bool isCalleeStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
3068 if (isCalleeStructRet || isCallerStructRet)
3082 (!
TT.isOSWindows() ||
TT.isOSBinFormatELF() ||
TT.isOSBinFormatMachO()))
3089 getEffectiveCallingConv(CalleeCC, isVarArg),
3090 getEffectiveCallingConv(CallerCC, CallerF.
isVarArg()), MF,
C, Ins,
3096 const uint32_t *CallerPreserved =
TRI->getCallPreservedMask(MF, CallerCC);
3097 if (CalleeCC != CallerCC) {
3098 const uint32_t *CalleePreserved =
TRI->getCallPreservedMask(MF, CalleeCC);
3099 if (!
TRI->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
3112 if (!Outs.
empty()) {
3119 for (
unsigned i = 0, realArgIdx = 0, e = ArgLocs.size();
3121 ++i, ++realArgIdx) {
3124 SDValue Arg = OutVals[realArgIdx];
3128 if (VA.
needsCustom() && (RegVT == MVT::f64 || RegVT == MVT::v2f64)) {
3135 if (!ArgLocs[++i].isRegLoc())
3137 if (RegVT == MVT::v2f64) {
3138 if (!ArgLocs[++i].isRegLoc())
3140 if (!ArgLocs[++i].isRegLoc())
3165 CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
3174 StringRef IntKind =
F.getFnAttribute(
"interrupt").getValueAsString();
3187 if (IntKind ==
"" || IntKind ==
"IRQ" || IntKind ==
"FIQ" ||
3190 else if (IntKind ==
"SWI" || IntKind ==
"UNDEF")
3194 "must be one of: IRQ, FIQ, SWI, ABORT or UNDEF");
3221 bool isLittleEndian = Subtarget->
isLittle();
3233 "secure entry function would return value through pointer",
3239 for (
unsigned i = 0, realRVLocIdx = 0;
3241 ++i, ++realRVLocIdx) {
3245 SDValue Arg = OutVals[realRVLocIdx];
3246 bool ReturnF16 =
false;
3281 auto RetVT = Outs[realRVLocIdx].ArgVT;
3303 DAG.
getVTList(MVT::i32, MVT::i32), Half);
3307 HalfGPRs.
getValue(isLittleEndian ? 0 : 1), Glue);
3313 HalfGPRs.
getValue(isLittleEndian ? 1 : 0), Glue);
3325 DAG.
getVTList(MVT::i32, MVT::i32), Arg);
3327 fmrrd.
getValue(isLittleEndian ? 0 : 1), Glue);
3332 fmrrd.
getValue(isLittleEndian ? 1 : 0), Glue);
3376 return DAG.
getNode(RetNode, dl, MVT::Other, RetOps);
3379bool ARMTargetLowering::isUsedByReturnOnly(
SDNode *
N,
SDValue &Chain)
const {
3380 if (
N->getNumValues() != 1)
3382 if (!
N->hasNUsesOfValue(1, 0))
3390 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3392 TCChain =
Copy->getOperand(0);
3406 SDValue UseChain =
U->getOperand(0);
3414 if (
U->getOperand(
U->getNumOperands() - 1).getValueType() == MVT::Glue)
3422 if (!
Copy->hasOneUse())
3429 if (
Copy->getOperand(
Copy->getNumOperands()-1).getValueType() == MVT::Glue)
3431 TCChain =
Copy->getOperand(0);
3436 bool HasRet =
false;
3451bool ARMTargetLowering::mayBeEmittedAsTailCall(
const CallInst *CI)
const {
3469 &&
"LowerWRITE_REGISTER called for non-i64 type argument.");
3485 EVT PtrVT =
Op.getValueType();
3495 if (Subtarget->genExecuteOnly()) {
3497 auto T =
const_cast<Type*
>(
CP->getType());
3498 auto C =
const_cast<Constant*
>(
CP->getConstVal());
3509 return LowerGlobalAddress(GA, DAG);
3514 Align CPAlign =
CP->getAlign();
3516 CPAlign = std::max(CPAlign,
Align(4));
3517 if (
CP->isMachineConstantPoolEntry())
3529 if (Subtarget->genExecuteOnly() && !Subtarget->hasV8MBaselineOps())
3538 unsigned ARMPCLabelIndex = 0;
3541 const BlockAddress *BA = cast<BlockAddressSDNode>(
Op)->getBlockAddress();
3544 if (!IsPositionIndependent) {
3547 unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
3558 if (!IsPositionIndependent)
3589ARMTargetLowering::LowerGlobalTLSAddressDarwin(
SDValue Op,
3592 "This function expects a Darwin target");
3597 SDValue DescAddr = LowerGlobalAddressDarwin(
Op, DAG);
3603 MVT::i32,
DL, Chain, DescAddr,
3627 Chain, FuncTLVGet, DAG.
getRegister(ARM::R0, MVT::i32),
3633ARMTargetLowering::LowerGlobalTLSAddressWindows(
SDValue Op,
3650 DAG.
getVTList(MVT::i32, MVT::Other), Ops);
3677 const auto *GA = cast<GlobalAddressSDNode>(
Op);
3694 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3716 Args.push_back(Entry);
3724 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
3725 return CallResult.first;
3747 unsigned char PCAdj = Subtarget->isThumb() ? 4 : 8;
3755 PtrVT, dl, Chain,
Offset,
3757 Chain =
Offset.getValue(1);
3763 PtrVT, dl, Chain,
Offset,
3773 PtrVT, dl, Chain,
Offset,
3789 return LowerGlobalTLSAddressDarwin(
Op, DAG);
3792 return LowerGlobalTLSAddressWindows(
Op, DAG);
3801 return LowerToTLSGeneralDynamicModel(GA, DAG);
3804 return LowerToTLSExecModels(GA, DAG, model);
3813 while (!Worklist.
empty()) {
3815 if (isa<ConstantExpr>(U)) {
3820 auto *
I = dyn_cast<Instruction>(U);
3821 if (!
I ||
I->getParent()->getParent() !=
F)
3849 auto *GVar = dyn_cast<GlobalVariable>(GV);
3850 if (!GVar || !GVar->hasInitializer() ||
3851 !GVar->isConstant() || !GVar->hasGlobalUnnamedAddr() ||
3852 !GVar->hasLocalLinkage())
3857 auto *
Init = GVar->getInitializer();
3859 Init->needsDynamicRelocation())
3868 auto *CDAInit = dyn_cast<ConstantDataArray>(
Init);
3871 unsigned RequiredPadding = 4 - (
Size % 4);
3872 bool PaddingPossible =
3873 RequiredPadding == 4 || (CDAInit && CDAInit->isString());
3878 unsigned PaddedSize =
Size + ((RequiredPadding == 4) ? 0 : RequiredPadding);
3902 if (RequiredPadding != 4) {
3907 while (RequiredPadding--)
3919 ++NumConstpoolPromoted;
3924 if (
const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
3925 if (!(GV = GA->getAliaseeObject()))
3927 if (
const auto *V = dyn_cast<GlobalVariable>(GV))
3928 return V->isConstant();
3929 return isa<Function>(GV);
3937 return LowerGlobalAddressWindows(
Op, DAG);
3939 return LowerGlobalAddressELF(
Op, DAG);
3941 return LowerGlobalAddressDarwin(
Op, DAG);
3949 const GlobalValue *GV = cast<GlobalAddressSDNode>(
Op)->getGlobal();
3953 if (GV->
isDSOLocal() && !Subtarget->genExecuteOnly())
3966 }
else if (Subtarget->
isROPI() && IsRO) {
3971 }
else if (Subtarget->
isRWPI() && !IsRO) {
3996 if (Subtarget->
useMovt() || Subtarget->genExecuteOnly()) {
4015 "ROPI/RWPI not currently supported for Darwin");
4018 const GlobalValue *GV = cast<GlobalAddressSDNode>(
Op)->getGlobal();
4041 "Windows on ARM expects to use movw/movt");
4043 "ROPI/RWPI not currently supported for Windows");
4046 const GlobalValue *GV = cast<GlobalAddressSDNode>(
Op)->getGlobal();
4050 else if (!
TM.shouldAssumeDSOLocal(GV))
4074 DAG.
getVTList(MVT::i32, MVT::Other),
Op.getOperand(0),
4075 Op.getOperand(1), Val);
4092SDValue ARMTargetLowering::LowerINTRINSIC_VOID(
4095 Op.getConstantOperandVal(
Op.getOperand(0).getValueType() == MVT::Other);
4099 case Intrinsic::arm_gnu_eabi_mcount: {
4108 assert(Mask &&
"Missing call preserved mask for calling convention");
4113 constexpr EVT ResultTys[] = {MVT::Other, MVT::Glue};
4117 if (Subtarget->isThumb())
4120 ARM::tBL_PUSHLR, dl, ResultTys,
4121 {ReturnAddress, DAG.getTargetConstant(ARMCC::AL, dl, PtrVT),
4122 DAG.getRegister(0, PtrVT), Callee, RegisterMask, Chain}),
4126 {ReturnAddress, Callee, RegisterMask, Chain}),
4135 unsigned IntNo =
Op.getConstantOperandVal(0);
4139 case Intrinsic::thread_pointer: {
4143 case Intrinsic::arm_cls: {
4144 const SDValue &Operand =
Op.getOperand(1);
4145 const EVT VTy =
Op.getValueType();
4156 case Intrinsic::arm_cls64: {
4159 const SDValue &Operand =
Op.getOperand(1);
4160 const EVT VTy =
Op.getValueType();
4183 case Intrinsic::eh_sjlj_lsda: {
4190 unsigned PCAdj = IsPositionIndependent ? (Subtarget->isThumb() ? 4 : 8) : 0;
4200 if (IsPositionIndependent) {
4206 case Intrinsic::arm_neon_vabs:
4209 case Intrinsic::arm_neon_vabds:
4210 if (
Op.getValueType().isInteger())
4212 Op.getOperand(1),
Op.getOperand(2));
4214 case Intrinsic::arm_neon_vabdu:
4216 Op.getOperand(1),
Op.getOperand(2));
4217 case Intrinsic::arm_neon_vmulls:
4218 case Intrinsic::arm_neon_vmullu: {
4219 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmulls)
4222 Op.getOperand(1),
Op.getOperand(2));
4224 case Intrinsic::arm_neon_vminnm:
4225 case Intrinsic::arm_neon_vmaxnm: {
4226 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminnm)
4229 Op.getOperand(1),
Op.getOperand(2));
4231 case Intrinsic::arm_neon_vminu:
4232 case Intrinsic::arm_neon_vmaxu: {
4233 if (
Op.getValueType().isFloatingPoint())
4235 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vminu)
4238 Op.getOperand(1),
Op.getOperand(2));
4240 case Intrinsic::arm_neon_vmins:
4241 case Intrinsic::arm_neon_vmaxs: {
4243 if (!
Op.getValueType().isFloatingPoint()) {
4244 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
4247 Op.getOperand(1),
Op.getOperand(2));
4249 unsigned NewOpc = (IntNo == Intrinsic::arm_neon_vmins)
4252 Op.getOperand(1),
Op.getOperand(2));
4254 case Intrinsic::arm_neon_vtbl1:
4256 Op.getOperand(1),
Op.getOperand(2));
4257 case Intrinsic::arm_neon_vtbl2:
4259 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4260 case Intrinsic::arm_mve_pred_i2v:
4261 case Intrinsic::arm_mve_pred_v2i:
4264 case Intrinsic::arm_mve_vreinterpretq:
4267 case Intrinsic::arm_mve_lsll:
4269 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4270 case Intrinsic::arm_mve_asrl:
4272 Op.getOperand(1),
Op.getOperand(2),
Op.getOperand(3));
4283 if (!Subtarget->hasDataBarrier()) {
4287 assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() &&
4288 "Unexpected ISD::ATOMIC_FENCE encountered. Should be libcall!");
4299 }
else if (Subtarget->preferISHSTBarriers() &&
4308 DAG.
getConstant(Intrinsic::arm_dmb, dl, MVT::i32),
4316 (!Subtarget->
isThumb1Only() && Subtarget->hasV5TEOps())))
4318 return Op.getOperand(0);
4321 unsigned isRead =
~Op.getConstantOperandVal(2) & 1;
4323 (!Subtarget->hasV7Ops() || !Subtarget->hasMPExtension()))
4325 return Op.getOperand(0);
4327 unsigned isData =
Op.getConstantOperandVal(4);
4328 if (Subtarget->isThumb()) {
4330 isRead = ~isRead & 1;
4331 isData = ~isData & 1;
4348 const Value *SV = cast<SrcValueSDNode>(
Op.getOperand(2))->getValue();
4349 return DAG.
getStore(
Op.getOperand(0), dl, FR,
Op.getOperand(1),
4357 const SDLoc &dl)
const {
4363 RC = &ARM::tGPRRegClass;
4365 RC = &ARM::GPRRegClass;
4379 MVT::i32, dl, Root, FIN,
4400 const Value *OrigArg,
4401 unsigned InRegsParamRecordIdx,
4402 int ArgOffset,
unsigned ArgSize)
const {
4417 unsigned RBegin, REnd;
4427 ArgOffset = -4 * (ARM::R4 - RBegin);
4437 for (
unsigned Reg = RBegin, i = 0;
Reg < REnd; ++
Reg, ++i) {
4446 if (!MemOps.
empty())
4455 unsigned TotalArgRegsSaveSize,
4456 bool ForceMutable)
const {
4467 CCInfo.
getStackSize(), std::max(4U, TotalArgRegsSaveSize));
4471bool ARMTargetLowering::splitValueIntoRegisterParts(
4473 unsigned NumParts,
MVT PartVT, std::optional<CallingConv::ID>
CC)
const {
4475 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4487SDValue ARMTargetLowering::joinRegisterPartsIntoValue(
4489 MVT PartVT,
EVT ValueVT, std::optional<CallingConv::ID>
CC)
const {
4490 if ((ValueVT == MVT::f16 || ValueVT == MVT::bf16) && PartVT == MVT::f32) {
4503SDValue ARMTargetLowering::LowerFormalArguments(
4519 unsigned CurArgIdx = 0;
4531 unsigned ArgRegBegin = ARM::R4;
4538 if (!
Flags.isByVal())
4542 unsigned RBegin, REnd;
4544 ArgRegBegin = std::min(ArgRegBegin, RBegin);
4550 int lastInsIndex = -1;
4554 ArgRegBegin = std::min(ArgRegBegin, (
unsigned)
GPRArgRegs[RegIdx]);
4557 unsigned TotalArgRegsSaveSize = 4 * (ARM::R4 - ArgRegBegin);
4561 for (
unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
4563 if (Ins[VA.
getValNo()].isOrigArg()) {
4564 std::advance(CurOrigArg,
4565 Ins[VA.
getValNo()].getOrigArgIndex() - CurArgIdx);
4577 GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4584 MVT::f64, dl, Chain, FIN,
4587 ArgValue2 = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4595 ArgValue = GetF64FormalArgument(VA, ArgLocs[++i], Chain, DAG, dl);
4599 if (RegVT == MVT::f16 || RegVT == MVT::bf16)
4600 RC = &ARM::HPRRegClass;
4601 else if (RegVT == MVT::f32)
4602 RC = &ARM::SPRRegClass;
4603 else if (RegVT == MVT::f64 || RegVT == MVT::v4f16 ||
4604 RegVT == MVT::v4bf16)
4605 RC = &ARM::DPRRegClass;
4606 else if (RegVT == MVT::v2f64 || RegVT == MVT::v8f16 ||
4607 RegVT == MVT::v8bf16)
4608 RC = &ARM::QPRRegClass;
4609 else if (RegVT == MVT::i32)
4611 : &ARM::GPRRegClass;
4657 assert(VA.
getValVT() != MVT::i64 &&
"i64 should already be lowered");
4663 if (index != lastInsIndex)
4671 if (
Flags.isByVal()) {
4672 assert(Ins[index].isOrigArg() &&
4673 "Byval arguments cannot be implicit");
4677 CCInfo, DAG, dl, Chain, &*CurOrigArg, CurByValIndex,
4692 lastInsIndex = index;
4699 VarArgStyleRegisters(CCInfo, DAG, dl, Chain, CCInfo.
getStackSize(),
4700 TotalArgRegsSaveSize);
4704 "secure entry function must not be variadic", dl.
getDebugLoc());
4715 StackArgSize =
alignTo(StackArgSize,
DL.getStackAlignment());
4724 "secure entry function requires arguments on stack", dl.
getDebugLoc());
4734 return CFP->getValueAPF().isPosZero();
4738 SDValue WrapperOp =
Op.getOperand(1).getOperand(0);
4740 if (
const ConstantFP *CFP = dyn_cast<ConstantFP>(CP->getConstVal()))
4741 return CFP->getValueAPF().isPosZero();
4744 Op->getValueType(0) == MVT::f64) {
4759 const SDLoc &dl)
const {
4761 unsigned C = RHSC->getZExtValue();
4827 LHS.getValueType() == MVT::i32 && isa<ConstantSDNode>(RHS) &&
4829 unsigned Mask =
LHS.getConstantOperandVal(1);
4830 auto *RHSC = cast<ConstantSDNode>(
RHS.getNode());
4831 uint64_t RHSV = RHSC->getZExtValue();
4832 if (
isMask_32(Mask) && (RHSV & ~Mask) == 0 && Mask != 255 && Mask != 65535) {
4834 if (RHSV && (RHSV > 255 || (RHSV << ShiftBits) <= 255)) {
4849 isa<ConstantSDNode>(RHS) &&
RHS->getAsZExtVal() == 0x80000000U &&
4851 LHS.getConstantOperandVal(1) < 31) {
4852 unsigned ShiftAmt =
LHS.getConstantOperandVal(1) + 1;
4892 return DAG.
getNode(CompareType, dl, MVT::Glue, LHS, RHS);
4898 bool Signaling)
const {
4899 assert(Subtarget->hasFP64() ||
RHS.getValueType() != MVT::f64);
4903 dl, MVT::Glue, LHS, RHS);
4906 dl, MVT::Glue, LHS);
4914 unsigned Opc =
Cmp.getOpcode();
4917 return DAG.
getNode(Opc,
DL, MVT::Glue,
Cmp.getOperand(0),
Cmp.getOperand(1));
4921 Opc =
Cmp.getOpcode();
4935std::pair<SDValue, SDValue>
4938 assert(
Op.getValueType() == MVT::i32 &&
"Unsupported value type");
4950 switch (
Op.getOpcode()) {
4963 DAG.
getVTList(
Op.getValueType(), MVT::i32), LHS, RHS)
5002 return std::make_pair(
Value, OverflowCmp);
5013 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Op, DAG, ARMcc);
5019 EVT VT =
Op.getValueType();
5022 ARMcc, CCR, OverflowCmp);
5062 EVT VT =
Op.getValueType();
5066 switch (
Op.getOpcode()) {
5091 EVT VT =
Op.getValueType();
5092 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP() || Subtarget->
isThumb1Only())
5102 switch (
Op->getOpcode()) {
5118 switch (
Op->getOpcode()) {
5137 DAG.
getNode(NewOpcode, dl, MVT::i32,
5148 unsigned Opc =
Cond.getOpcode();
5150 if (
Cond.getResNo() == 1 &&
5158 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5160 EVT VT =
Op.getValueType();
5162 return getCMOV(dl, VT, SelectTrue, SelectFalse, ARMcc, CCR,
5173 dyn_cast<ConstantSDNode>(
Cond.getOperand(0));
5175 dyn_cast<ConstantSDNode>(
Cond.getOperand(1));
5177 if (CMOVTrue && CMOVFalse) {
5183 if (CMOVTrueVal == 1 && CMOVFalseVal == 0) {
5185 False = SelectFalse;
5186 }
else if (CMOVTrueVal == 0 && CMOVFalseVal == 1) {
5192 EVT VT =
Op.getValueType();
5197 return getCMOV(dl, VT, True, False, ARMcc, CCR, Cmp, DAG);
5213 bool &swpCmpOps,
bool &swpVselOps) {
5241 swpCmpOps = !swpCmpOps;
5242 swpVselOps = !swpVselOps;
5265 if (!Subtarget->hasFP64() && VT == MVT::f64) {
5267 DAG.
getVTList(MVT::i32, MVT::i32), FalseVal);
5269 DAG.
getVTList(MVT::i32, MVT::i32), TrueVal);
5279 ARMcc, CCR, duplicateCmp(Cmp, DAG));
5306 ((K ==
LHS && K == TrueVal) || (K ==
RHS && K == FalseVal))) ||
5308 ((K ==
RHS && K == TrueVal) || (K ==
LHS && K == FalseVal)));
5329 EVT VT =
Op.getValueType();
5336 const SDValue Op2 = isa<ConstantSDNode>(TrueVal1) ? FalseVal1 : TrueVal1;
5351 if (V1Tmp != TrueVal1 || V2Tmp != TrueVal2 || K1 != FalseVal1 ||
5359 if (!isa<ConstantSDNode>(K1) || !isa<ConstantSDNode>(K2))
5362 int64_t Val1 = cast<ConstantSDNode>(K1)->getSExtValue();
5363 int64_t Val2 = cast<ConstantSDNode>(K2)->getSExtValue();
5364 int64_t PosVal = std::max(Val1, Val2);
5365 int64_t NegVal = std::min(Val1, Val2);
5411 SDValue KTmp = isa<ConstantSDNode>(TrueVal) ? TrueVal : FalseVal;
5412 V = (KTmp == TrueVal) ? FalseVal : TrueVal;
5417 if (*K != KTmp || V != VTmp)
5428bool ARMTargetLowering::isUnsupportedFloatingType(
EVT VT)
const {
5432 return !Subtarget->hasFP64();
5434 return !Subtarget->hasFullFP16();
5439 EVT VT =
Op.getValueType();
5443 if ((!Subtarget->isThumb() && Subtarget->hasV6Ops()) || Subtarget->
isThumb2())
5455 if (VT == MVT::i32 &&
5475 if (Subtarget->hasV8_1MMainlineOps() && CFVal && CTVal &&
5476 LHS.getValueType() == MVT::i32 &&
RHS.getValueType() == MVT::i32) {
5479 unsigned Opcode = 0;
5481 if (TVal == ~FVal) {
5483 }
else if (TVal == ~FVal + 1) {
5485 }
else if (TVal + 1 == FVal) {
5487 }
else if (TVal == FVal + 1) {
5519 return DAG.
getNode(Opcode, dl, VT, TrueVal, FalseVal, ARMcc, Cmp);
5523 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5525 DAG,
LHS.getValueType(), LHS, RHS,
CC, dl, LHS, RHS);
5529 if (!
RHS.getNode()) {
5535 if (
LHS.getValueType() == MVT::i32) {
5547 TrueVal.getValueType() == MVT::f32 ||
5548 TrueVal.getValueType() == MVT::f64)) {
5563 return getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, CCR, Cmp, DAG);
5575 (
TrueVal.getValueType() == MVT::f16 ||
5576 TrueVal.getValueType() == MVT::f32 ||
5577 TrueVal.getValueType() == MVT::f64)) {
5578 bool swpCmpOps =
false;
5579 bool swpVselOps =
false;
5594 SDValue Result = getCMOV(dl, VT, FalseVal, TrueVal, ARMcc, CCR, Cmp, DAG);
5598 SDValue Cmp2 = getVFPCmp(LHS, RHS, DAG, dl);
5599 Result = getCMOV(dl, VT, Result, TrueVal, ARMcc2, CCR, Cmp2, DAG);
5609 if (!
N->hasOneUse())
5612 if (!
N->getNumValues())
5614 EVT VT =
Op.getValueType();
5615 if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
5632 return DAG.
getLoad(MVT::i32,
SDLoc(
Op), Ld->getChain(), Ld->getBasePtr(),
5633 Ld->getPointerInfo(), Ld->getAlign(),
5634 Ld->getMemOperand()->getFlags());
5652 DAG.
getLoad(MVT::i32, dl, Ld->getChain(),
Ptr, Ld->getPointerInfo(),
5653 Ld->getAlign(), Ld->getMemOperand()->getFlags());
5655 EVT PtrType =
Ptr.getValueType();
5658 RetVal2 = DAG.
getLoad(MVT::i32, dl, Ld->getChain(), NewPtr,
5659 Ld->getPointerInfo().getWithOffset(4),
5661 Ld->getMemOperand()->getFlags());
5679 bool LHSSeenZero =
false;
5681 bool RHSSeenZero =
false;
5683 if (LHSOk && RHSOk && (LHSSeenZero || RHSSeenZero)) {
5694 if (
LHS.getValueType() == MVT::f32) {
5702 Chain, Dest, ARMcc, CCR, Cmp);
5714 SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
5729 unsigned Opc =
Cond.getOpcode();
5732 if (
Cond.getResNo() == 1 &&
5742 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
Cond, DAG, ARMcc);
5766 if (isUnsupportedFloatingType(
LHS.getValueType())) {
5768 DAG,
LHS.getValueType(), LHS, RHS,
CC, dl, LHS, RHS);
5772 if (!
RHS.getNode()) {
5780 unsigned Opc =
LHS.getOpcode();
5794 std::tie(
Value, OverflowCmp) = getARMXALUOOp(
LHS.getValue(0), DAG, ARMcc);
5809 if (
LHS.getValueType() == MVT::i32) {
5814 Chain, Dest, ARMcc, CCR, Cmp);
5820 if (
SDValue Result = OptimizeVFPBrcond(
Op, DAG))
5831 SDValue Ops[] = { Chain, Dest, ARMcc, CCR,
Cmp };
5853 if (Subtarget->
isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) {
5859 Addr,
Op.getOperand(2), JTI);
5865 Chain =
Addr.getValue(1);
5872 Chain =
Addr.getValue(1);
5878 EVT VT =
Op.getValueType();
5881 if (
Op.getValueType().getVectorElementType() == MVT::i32) {
5882 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::f32)
5890 const EVT OpTy =
Op.getOperand(0).getValueType();
5891 if (OpTy == MVT::v4f32)
5893 else if (OpTy == MVT::v4f16 && HasFullFP16)
5895 else if (OpTy == MVT::v8f16 && HasFullFP16)
5900 if (VT != MVT::v4i16 && VT != MVT::v8i16)
5903 Op = DAG.
getNode(
Op.getOpcode(), dl, NewTy,
Op.getOperand(0));
5908 EVT VT =
Op.getValueType();
5912 bool IsStrict =
Op->isStrictFPOpcode();
5913 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
5915 if (isUnsupportedFloatingType(SrcVal.
getValueType())) {
5925 MakeLibCallOptions CallOptions;
5928 std::tie(Result, Chain) =
makeLibCall(DAG, LC,
Op.getValueType(), SrcVal,
5929 CallOptions, Loc, Chain);
5939 Loc,
Op.getValueType(), SrcVal);
5948 EVT VT =
Op.getValueType();
5949 EVT ToVT = cast<VTSDNode>(
Op.getOperand(1))->getVT();
5950 EVT FromVT =
Op.getOperand(0).getValueType();
5952 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f32)
5954 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f64 &&
5955 Subtarget->hasFP64())
5957 if (VT == MVT::i32 && ToVT == MVT::i32 && FromVT == MVT::f16 &&
5958 Subtarget->hasFullFP16())
5960 if (VT == MVT::v4i32 && ToVT == MVT::i32 && FromVT == MVT::v4f32 &&
5961 Subtarget->hasMVEFloatOps())
5963 if (VT == MVT::v8i16 && ToVT == MVT::i16 && FromVT == MVT::v8f16 &&
5964 Subtarget->hasMVEFloatOps())
5967 if (FromVT != MVT::v4f32 && FromVT != MVT::v8f16)
5984 EVT VT =
Op.getValueType();
5987 if (
Op.getOperand(0).getValueType().getVectorElementType() == MVT::i32) {
5993 assert((
Op.getOperand(0).getValueType() == MVT::v4i16 ||
5994 Op.getOperand(0).getValueType() == MVT::v8i16) &&
5995 "Invalid type for custom lowering!");
6000 if (VT == MVT::v4f32)
6001 DestVecType = MVT::v4i32;
6002 else if (VT == MVT::v4f16 && HasFullFP16)
6003 DestVecType = MVT::v4i16;
6004 else if (VT == MVT::v8f16 && HasFullFP16)
6005 DestVecType = MVT::v8i16;
6011 switch (
Op.getOpcode()) {
6023 Op = DAG.
getNode(CastOpc, dl, DestVecType,
Op.getOperand(0));
6028 EVT VT =
Op.getValueType();
6031 if (isUnsupportedFloatingType(VT)) {
6039 MakeLibCallOptions CallOptions;
6041 CallOptions,
SDLoc(
Op)).first;
6052 EVT VT =
Op.getValueType();
6056 bool UseNEON = !InGPR && Subtarget->hasNEON();
6063 EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
6070 if (SrcVT == MVT::f32) {
6076 }
else if (VT == MVT::f32)
6092 if (VT == MVT::f32) {
6104 if (SrcVT == MVT::f64)
6113 if (VT == MVT::f32) {
6137 EVT VT =
Op.getValueType();
6139 unsigned Depth =
Op.getConstantOperandVal(0);
6141 SDValue FrameAddr = LowerFRAMEADDR(
Op, DAG);
6160 EVT VT =
Op.getValueType();
6162 unsigned Depth =
Op.getConstantOperandVal(0);
6176 .
Case(
"sp", ARM::SP)
6191 assert(
N->getValueType(0) == MVT::i64
6192 &&
"ExpandREAD_REGISTER called for non-i64 type result.");
6195 DAG.
getVTList(MVT::i32, MVT::i32, MVT::Other),
6235 const APInt &APIntIndex =
Index->getAPIntValue();
6237 NewIndex *= APIntIndex;
6267 EVT SrcVT =
Op.getValueType();
6268 EVT DstVT =
N->getValueType(0);
6270 if ((SrcVT == MVT::i16 || SrcVT == MVT::i32) &&
6271 (DstVT == MVT::f16 || DstVT == MVT::bf16))
6275 if ((DstVT == MVT::i16 || DstVT == MVT::i32) &&
6276 (SrcVT == MVT::f16 || SrcVT == MVT::bf16))
6281 if (!(SrcVT == MVT::i64 || DstVT == MVT::i64))
6285 if (SrcVT == MVT::i64 && TLI.
isTypeLegal(DstVT)) {
6297 if (DstVT == MVT::i64 && TLI.
isTypeLegal(SrcVT)) {
6334 EVT VT =
Op.getValueType();
6353 SDValue LoBigShift = DAG.
getNode(Opc, dl, VT, ShOpHi, ExtraShAmt);
6361 ? DAG.
getNode(Opc, dl, VT, ShOpHi,
6378 EVT VT =
Op.getValueType();
6421 DAG.
getConstant(Intrinsic::arm_get_fpscr, dl, MVT::i32)};
6473 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6501 Chain, DAG.
getConstant(Intrinsic::arm_set_fpscr,
DL, MVT::i32), FPSCR};
6531 EVT VT =
N->getValueType(0);
6532 if (VT.
isVector() && ST->hasNEON()) {
6541 if (ElemTy == MVT::i8) {
6549 if ((ElemTy == MVT::i16 || ElemTy == MVT::i32) &&
6564 if (ElemTy == MVT::i64) {
6577 if (!ST->hasV6T2Ops())
6586 EVT VT =
N->getValueType(0);
6589 assert(ST->hasNEON() &&
"Custom ctpop lowering requires NEON.");
6590 assert((VT == MVT::v1i64 || VT == MVT::v2i64 || VT == MVT::v2i32 ||
6591 VT == MVT::v4i32 || VT == MVT::v4i16 || VT == MVT::v8i16) &&
6592 "Unexpected type for custom ctpop lowering");
6600 unsigned EltSize = 8;
6623 Op =
Op.getOperand(0);
6625 APInt SplatBits, SplatUndef;
6626 unsigned SplatBitSize;
6629 !BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
6631 SplatBitSize > ElementBits)
6642 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6646 return (Cnt >= 0 && (isLong ? Cnt - 1 : Cnt) < ElementBits);
6657 assert(VT.
isVector() &&
"vector shift count is not a vector type");
6662 return (Cnt >= 1 && Cnt <= (isNarrow ? ElementBits / 2 : ElementBits));
6663 if (Cnt >= -(isNarrow ? ElementBits / 2 : ElementBits) && Cnt <= -1) {
6672 EVT VT =
N->getValueType(0);
6694 "unexpected vector shift opcode");
6696 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
6697 unsigned VShiftOpc =
6699 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
6705 EVT ShiftVT =
N->getOperand(1).getValueType();
6708 unsigned VShiftOpc =
6710 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0), NegatedCount);
6715 EVT VT =
N->getValueType(0);
6724 "Unknown shift to lower!");
6726 unsigned ShOpc =
N->getOpcode();
6727 if (ST->hasMVEIntegerOps()) {
6757 DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6771 if (ST->isThumb1Only())
6776 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(0), dl, MVT::i32, MVT::i32);
6792 bool Invert =
false;
6799 EVT VT =
Op.getValueType();
6807 assert(ST->hasMVEIntegerOps() &&
6808 "No hardware support for integer vector comparison!");
6810 if (
Op.getValueType().getVectorElementType() != MVT::i1)
6835 Merged = DAG.
getNOT(dl, Merged, CmpVT);
6845 switch (SetCCOpcode) {
6849 if (ST->hasMVEFloatOps()) {
6852 Invert =
true; [[fallthrough]];
6857 case ISD::SETLT: Swap =
true; [[fallthrough]];
6861 case ISD::SETLE: Swap =
true; [[fallthrough]];
6877 Result = DAG.
getNOT(dl, Result, VT);
6880 case ISD::SETUO: Invert =
true; [[fallthrough]];
6889 Result = DAG.
getNOT(dl, Result, VT);
6895 switch (SetCCOpcode) {
6898 if (ST->hasMVEIntegerOps()) {
6901 Invert =
true; [[fallthrough]];
6904 case ISD::SETLT: Swap =
true; [[fallthrough]];
6906 case ISD::SETLE: Swap =
true; [[fallthrough]];
6915 if (ST->hasNEON() && Opc ==
ARMCC::EQ) {
6931 Result = DAG.
getNOT(dl, Result, VT);
6965 Result = DAG.
getNOT(dl, Result, VT);
6977 assert(
LHS.getSimpleValueType().isInteger() &&
"SETCCCARRY is integer only.");
7007 unsigned OpCmode, Imm;
7018 switch (SplatBitSize) {
7023 assert((SplatBits & ~0xff) == 0 &&
"one byte splat value is too big");
7026 VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
7031 VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
7032 if ((SplatBits & ~0xff) == 0) {
7038 if ((SplatBits & ~0xff00) == 0) {
7041 Imm = SplatBits >> 8;
7051 VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
7052 if ((SplatBits & ~0xff) == 0) {
7058 if ((SplatBits & ~0xff00) == 0) {
7061 Imm = SplatBits >> 8;
7064 if ((SplatBits & ~0xff0000) == 0) {
7067 Imm = SplatBits >> 16;
7070 if ((SplatBits & ~0xff000000) == 0) {
7073 Imm = SplatBits >> 24;
7080 if ((SplatBits & ~0xffff) == 0 &&
7081 ((SplatBits | SplatUndef) & 0xff) == 0xff) {
7084 Imm = SplatBits >> 8;
7092 if ((SplatBits & ~0xffffff) == 0 &&
7093 ((SplatBits | SplatUndef) & 0xffff) == 0xffff) {
7096 Imm = SplatBits >> 16;
7112 unsigned ImmMask = 1;
7114 for (
int ByteNum = 0; ByteNum < 8; ++ByteNum) {
7115 if (((SplatBits | SplatUndef) & BitMask) == BitMask) {
7117 }
else if ((SplatBits & BitMask) != 0) {
7127 unsigned Mask = (1 << BytesPerElem) - 1;
7128 unsigned NumElems = 8 / BytesPerElem;
7129 unsigned NewImm = 0;
7130 for (
unsigned ElemNum = 0; ElemNum < NumElems; ++ElemNum) {
7131 unsigned Elem = ((Imm >> ElemNum * BytesPerElem) & Mask);
7132 NewImm |= Elem << (NumElems - ElemNum - 1) * BytesPerElem;
7139 VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
7153 EVT VT =
Op.getValueType();
7154 bool IsDouble = (VT == MVT::f64);
7160 if (
ST->genExecuteOnly()) {
7162 assert((!
ST->isThumb1Only() ||
ST->hasV8MBaselineOps()) &&
7163 "Unexpected architecture");
7186 if (!
ST->hasVFP3Base())
7191 if (IsDouble && !Subtarget->hasFP64())
7198 if (IsDouble || !
ST->useNEONForSinglePrecisionFP()) {
7216 if (!
ST->hasNEON() || (!IsDouble && !
ST->useNEONForSinglePrecisionFP()))
7225 if (IsDouble && (iVal & 0xffffffff) != (iVal >> 32))
7279 unsigned ExpectedElt = Imm;
7280 for (
unsigned i = 1; i < NumElts; ++i) {
7284 if (ExpectedElt == NumElts)
7287 if (M[i] < 0)
continue;
7288 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7296 bool &ReverseVEXT,
unsigned &Imm) {
7298 ReverseVEXT =
false;
7309 unsigned ExpectedElt = Imm;
7310 for (
unsigned i = 1; i < NumElts; ++i) {
7314 if (ExpectedElt == NumElts * 2) {
7319 if (M[i] < 0)
continue;
7320 if (ExpectedElt !=
static_cast<unsigned>(M[i]))
7335 return VT == MVT::v8i8 && M.size() == 8;
7340 if (Mask.size() == Elements * 2)
7341 return Index / Elements;
7342 return Mask[
Index] == 0 ? 0 : 1;
7372 if (M.size() != NumElts && M.size() != NumElts*2)
7380 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7382 for (
unsigned j = 0; j < NumElts; j += 2) {
7383 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7384 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + NumElts + WhichResult))
7389 if (M.size() == NumElts*2)
7404 if (M.size() != NumElts && M.size() != NumElts*2)
7407 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7409 for (
unsigned j = 0; j < NumElts; j += 2) {
7410 if ((M[i+j] >= 0 && (
unsigned) M[i+j] != j + WhichResult) ||
7411 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] != j + WhichResult))
7416 if (M.size() == NumElts*2)
7436 if (M.size() != NumElts && M.size() != NumElts*2)
7439 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7441 for (
unsigned j = 0; j < NumElts; ++j) {
7442 if (M[i+j] >= 0 && (
unsigned) M[i+j] != 2 * j + WhichResult)
7447 if (M.size() == NumElts*2)
7466 if (M.size() != NumElts && M.size() != NumElts*2)
7469 unsigned Half = NumElts / 2;
7470 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7472 for (
unsigned j = 0; j < NumElts; j += Half) {
7473 unsigned Idx = WhichResult;
7474 for (
unsigned k = 0; k < Half; ++k) {
7475 int MIdx = M[i + j + k];
7476 if (MIdx >= 0 && (
unsigned) MIdx !=
Idx)
7483 if (M.size() == NumElts*2)
7507 if (M.size() != NumElts && M.size() != NumElts*2)
7510 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7512 unsigned Idx = WhichResult * NumElts / 2;
7513 for (
unsigned j = 0; j < NumElts; j += 2) {
7514 if ((M[i+j] >= 0 && (
unsigned) M[i+j] !=
Idx) ||
7515 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] !=
Idx + NumElts))
7521 if (M.size() == NumElts*2)
7540 if (M.size() != NumElts && M.size() != NumElts*2)
7543 for (
unsigned i = 0; i < M.size(); i += NumElts) {
7545 unsigned Idx = WhichResult * NumElts / 2;
7546 for (
unsigned j = 0; j < NumElts; j += 2) {
7547 if ((M[i+j] >= 0 && (
unsigned) M[i+j] !=
Idx) ||
7548 (M[i+j+1] >= 0 && (
unsigned) M[i+j+1] !=
Idx))
7554 if (M.size() == NumElts*2)
7567 unsigned &WhichResult,
7570 if (
isVTRNMask(ShuffleMask, VT, WhichResult))
7572 if (
isVUZPMask(ShuffleMask, VT, WhichResult))
7574 if (
isVZIPMask(ShuffleMask, VT, WhichResult))
7592 if (NumElts != M.size())
7596 for (
unsigned i = 0; i != NumElts; ++i)
7597 if (M[i] >= 0 && M[i] != (
int) (NumElts - 1 - i))
7606 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7614 int Ofs = Top ? 1 : 0;
7615 int Upper = SingleSource ? 0 : NumElts;
7616 for (
int i = 0, e = NumElts / 2; i != e; ++i) {
7617 if (M[i] >= 0 && M[i] != (i * 2) + Ofs)
7619 if (M[i + e] >= 0 && M[i + e] != (i * 2) + Ofs +
Upper)
7628 if (NumElts != M.size() || (VT != MVT::v8i16 && VT != MVT::v16i8))
7637 unsigned Offset = Top ? 0 : 1;
7638 unsigned N = SingleSource ? 0 : NumElts;
7639 for (
unsigned i = 0; i < NumElts; i += 2) {
7640 if (M[i] >= 0 && M[i] != (
int)i)
7642 if (M[i + 1] >= 0 && M[i + 1] != (
int)(
N + i +
Offset))
7651 if (NumElts != M.size())
7659 unsigned Off0 = rev ? NumElts / 2 : 0;
7660 unsigned Off1 = rev ? 0 : NumElts / 2;
7661 for (
unsigned i = 0; i < NumElts; i += 2) {
7662 if (M[i] >= 0 && M[i] != (
int)(Off0 + i / 2))
7664 if (M[i + 1] >= 0 && M[i + 1] != (
int)(Off1 + i / 2))
7680 if (!ST->hasMVEFloatOps())
7685 if (VT != MVT::v8f16)
7706 for (
unsigned i = 1; i < 4; i++) {
7733 if (!ST->hasMVEFloatOps())
7738 if (VT != MVT::v4f32)
7754 for (
unsigned i = 1; i < 4; i++) {
7775 if (!isa<ConstantSDNode>(
N))
7777 Val =
N->getAsZExtVal();
7779 if (ST->isThumb1Only()) {
7780 if (Val <= 255 || ~Val <= 255)
7792 EVT VT =
Op.getValueType();
7794 assert(ST->hasMVEIntegerOps() &&
"LowerBUILD_VECTOR_i1 called without MVE!");
7798 unsigned BitsPerBool;
7802 }
else if (NumElts == 4) {
7805 }
else if (NumElts == 8) {
7808 }
else if (NumElts == 16) {
7817 if (!isa<ConstantSDNode>(FirstOp) &&
7819 return U.get().isUndef() || U.get() == FirstOp;
7827 unsigned Bits32 = 0;
7828 for (
unsigned i = 0; i < NumElts; ++i) {
7830 if (!isa<ConstantSDNode>(V) && !V.isUndef())
7832 bool BitSet = V.isUndef() ?
false : V->getAsZExtVal();
7834 Bits32 |= BoolMask << (i * BitsPerBool);
7840 for (
unsigned i = 0; i < NumElts; ++i) {
7842 if (isa<ConstantSDNode>(V) || V.isUndef())
7853 if (!ST->hasMVEIntegerOps())
7857 EVT VT =
Op.getValueType();
7867 if (
N != 1 &&
N != 2 &&
N != 4 &&
N != 8)
7871 for (
unsigned I = 2;
I < NumElts;
I++) {
7887 switch (
N->getOpcode()) {
7896 return N->getOperand(1).getNode() ==
Op;
7898 switch (
N->getConstantOperandVal(0)) {
7899 case Intrinsic::arm_mve_add_predicated:
7900 case Intrinsic::arm_mve_mul_predicated:
7901 case Intrinsic::arm_mve_qadd_predicated:
7902 case Intrinsic::arm_mve_vhadd:
7903 case Intrinsic::arm_mve_hadd_predicated:
7904 case Intrinsic::arm_mve_vqdmulh:
7905 case Intrinsic::arm_mve_qdmulh_predicated:
7906 case Intrinsic::arm_mve_vqrdmulh:
7907 case Intrinsic::arm_mve_qrdmulh_predicated:
7908 case Intrinsic::arm_mve_vqdmull:
7909 case Intrinsic::arm_mve_vqdmull_predicated:
7911 case Intrinsic::arm_mve_sub_predicated:
7912 case Intrinsic::arm_mve_qsub_predicated:
7913 case Intrinsic::arm_mve_vhsub:
7914 case Intrinsic::arm_mve_hsub_predicated:
7915 return N->getOperand(2).getNode() ==
Op;
7930 EVT VT =
Op.getValueType();
7938 APInt SplatBits, SplatUndef;
7939 unsigned SplatBitSize;
7941 if (BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
7948 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32) &&
7950 [BVN](
const SDNode *U) { return IsQRMVEInstruction(U, BVN); })) {
7951 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7952 : SplatBitSize == 16 ? MVT::v8i16
7959 if ((
ST->hasNEON() && SplatBitSize <= 64) ||
7960 (
ST->hasMVEIntegerOps() && SplatBitSize <= 64)) {
7965 SplatBitSize, DAG, dl, VmovVT, VT,
VMOVModImm);
7973 uint64_t NegatedImm = (~SplatBits).getZExtValue();
7975 NegatedImm, SplatUndef.
getZExtValue(), SplatBitSize, DAG, dl, VmovVT,
7983 if ((VT == MVT::v2f32 || VT == MVT::v4f32) && SplatBitSize == 32) {
7993 if (
ST->hasMVEIntegerOps() &&
7994 (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32)) {
7995 EVT DupVT = SplatBitSize == 32 ? MVT::v4i32
7996 : SplatBitSize == 16 ? MVT::v8i16
8013 bool isOnlyLowElement =
true;
8014 bool usesOnlyOneValue =
true;
8015 bool hasDominantValue =
false;
8022 for (
unsigned i = 0; i < NumElts; ++i) {
8027 isOnlyLowElement =
false;
8028 if (!isa<ConstantFPSDNode>(V) && !isa<ConstantSDNode>(V))
8031 ValueCounts.
insert(std::make_pair(V, 0));
8032 unsigned &Count = ValueCounts[
V];
8035 if (++Count > (NumElts / 2)) {
8036 hasDominantValue =
true;
8040 if (ValueCounts.
size() != 1)
8041 usesOnlyOneValue =
false;
8042 if (!
Value.getNode() && !ValueCounts.
empty())
8045 if (ValueCounts.
empty())
8057 if (hasDominantValue && EltSize <= 32) {
8068 (constIndex = dyn_cast<ConstantSDNode>(
Value->getOperand(1)))) {
8073 if (VT !=
Value->getOperand(0).getValueType()) {
8086 if (!usesOnlyOneValue) {
8089 for (
unsigned I = 0;
I < NumElts; ++
I) {
8104 assert(FVT == MVT::f32 || FVT == MVT::f16);
8105 MVT IVT = (FVT == MVT::f32) ? MVT::i32 : MVT::i16;
8106 for (
unsigned i = 0; i < NumElts; ++i)
8111 Val = LowerBUILD_VECTOR(Val, DAG, ST);
8115 if (usesOnlyOneValue) {
8142 if (
ST->hasNEON() && VT.
is128BitVector() && VT != MVT::v2f64 && VT != MVT::v4f32) {
8162 if (EltSize >= 32) {
8168 for (
unsigned i = 0; i < NumElts; ++i)
8182 for (
unsigned i = 0 ; i < NumElts; ++i) {
8201 EVT VT =
Op.getValueType();
8204 struct ShuffleSourceInfo {
8206 unsigned MinElt = std::numeric_limits<unsigned>::max();
8207 unsigned MaxElt = 0;
8217 int WindowScale = 1;
8219 ShuffleSourceInfo(
SDValue Vec) : Vec(Vec), ShuffleVec(Vec) {}
8221 bool operator ==(
SDValue OtherVec) {
return Vec == OtherVec; }
8227 for (
unsigned i = 0; i < NumElts; ++i) {
8235 }
else if (!isa<ConstantSDNode>(
V.getOperand(1))) {
8242 SDValue SourceVec =
V.getOperand(0);
8244 if (Source == Sources.
end())
8248 unsigned EltNo =
V.getConstantOperandVal(1);
8255 if (Sources.
size() > 2)
8261 for (
auto &Source : Sources) {
8262 EVT SrcEltTy =
Source.Vec.getValueType().getVectorElementType();
8263 if (SrcEltTy.
bitsLT(SmallestEltTy))
8264 SmallestEltTy = SrcEltTy;
8266 unsigned ResMultiplier =
8274 for (
auto &Src : Sources) {
8275 EVT SrcVT = Src.ShuffleVec.getValueType();
8279 if (SrcVTSize == VTSize)
8288 if (SrcVTSize < VTSize) {
8289 if (2 * SrcVTSize != VTSize)
8295 DAG.
getUNDEF(Src.ShuffleVec.getValueType()));
8299 if (SrcVTSize != 2 * VTSize)
8302 if (Src.MaxElt - Src.MinElt >= NumSrcElts) {
8307 if (Src.MinElt >= NumSrcElts) {
8312 Src.WindowBase = -NumSrcElts;
8313 }
else if (Src.MaxElt < NumSrcElts) {
8330 Src.WindowBase = -Src.MinElt;
8337 for (
auto &Src : Sources) {
8338 EVT SrcEltTy = Src.ShuffleVec.getValueType().getVectorElementType();
8339 if (SrcEltTy == SmallestEltTy)
8344 Src.WindowBase *= Src.WindowScale;
8350 assert(Src.ShuffleVec.getValueType() == ShuffleVT););
8357 if (
Entry.isUndef())
8361 int EltNo = cast<ConstantSDNode>(
Entry.getOperand(1))->getSExtValue();
8366 EVT OrigEltTy =
Entry.getOperand(0).getValueType().getVectorElementType();
8369 int LanesDefined = BitsDefined / BitsPerShuffleLane;
8373 int *LaneMask = &
Mask[i * ResMultiplier];
8375 int ExtractBase = EltNo * Src->WindowScale + Src->WindowBase;
8376 ExtractBase += NumElts * (Src - Sources.begin());
8377 for (
int j = 0;
j < LanesDefined; ++
j)
8378 LaneMask[j] = ExtractBase + j;
8384 assert(Sources.size() <= 2 &&
"Too many sources!");
8387 for (
unsigned i = 0; i < Sources.size(); ++i)
8416 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8436 unsigned PFIndexes[4];
8437 for (
unsigned i = 0; i != 4; ++i) {
8441 PFIndexes[i] = M[i];
8445 unsigned PFTableIndex =
8446 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8448 unsigned Cost = (PFEntry >> 30);
8454 bool ReverseVEXT, isV_UNDEF;
8455 unsigned Imm, WhichResult;
8458 if (EltSize >= 32 ||
8465 else if (Subtarget->hasNEON() &&
8470 else if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8473 else if (Subtarget->hasMVEIntegerOps() &&
8477 else if (Subtarget->hasMVEIntegerOps() &&
8491 unsigned OpNum = (PFEntry >> 26) & 0x0F;
8492 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
8493 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
8496 if (LHSID == (1*9+2)*9+3)
return LHS;
8497 assert(LHSID == ((4*9+5)*9+6)*9+7 &&
"Illegal OP_COPY!");
8554 for (
int I : ShuffleMask)
8557 if (V2.getNode()->isUndef())
8567 EVT VT =
Op.getValueType();
8569 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8570 "Expect an v8i16/v16i8 type");
8576 std::vector<int> NewMask;
8580 NewMask.push_back(i);
8620 if (VT != MVT::v16i1)
8636 EVT VT =
Op.getValueType();
8640 assert(ST->hasMVEIntegerOps() &&
8641 "No support for vector shuffle of boolean predicates");
8667 "Expected identical vector type in expanded i1 shuffle!");
8671 PredAsVector2, ShuffleMask);
8676 if (VT == MVT::v2i1) {
8693 EVT VT =
Op.getValueType();
8697 assert((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
8698 "Unexpected vector type");
8700 int QuarterSize = NumElts / 4;
8709 for (
int i = 0; i <
Length; i++) {
8710 if (ShuffleMask[Start + i] >= 0) {
8711 if (ShuffleMask[Start + i] %
Length != i)
8713 MovIdx = ShuffleMask[Start + i] /
Length;
8721 for (
int i = 1; i <
Length; i++) {
8722 if (ShuffleMask[Start + i] >= 0 &&
8723 (ShuffleMask[Start + i] /
Length != MovIdx ||
8724 ShuffleMask[Start + i] %
Length != i))
8730 for (
int Part = 0; Part < 4; ++Part) {
8732 int Elt = getMovIdx(ShuffleMask, Part * QuarterSize, QuarterSize);
8736 Input =
Op->getOperand(1);
8746 if (!Parts[0] && !Parts[1] && !Parts[2] && !Parts[3])
8751 if (!Parts[0] || !Parts[1] || !Parts[2] || !Parts[3]) {
8753 for (
int Part = 0; Part < 4; ++Part)
8754 for (
int i = 0; i < QuarterSize; i++)
8756 Parts[Part] ? -1 : ShuffleMask[Part * QuarterSize + i]);
8758 VT, dl,
Op->getOperand(0),
Op->getOperand(1), NewShuffleMask);
8761 for (
int Part = 0; Part < 4; ++Part)
8777 EVT VT =
Op.getValueType();
8789 for (
int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) {
8793 if (Mask[i] != i + BaseOffset) {
8794 if (OffElement == -1)
8800 return NonUndef > 2 && OffElement != -1;
8804 if (isOneOffIdentityMask(ShuffleMask, VT, 0, OffElement))
8806 else if (isOneOffIdentityMask(ShuffleMask, VT, NumElts, OffElement))
8817 ShuffleMask[OffElement] < (
int)NumElts ? V1 : V2,
8828 EVT VT =
Op.getValueType();
8832 if (ST->hasMVEIntegerOps() && EltSize == 1)
8843 if (EltSize <= 32) {
8847 if (Lane == -1) Lane = 0;
8858 bool IsScalarToVector =
true;
8861 IsScalarToVector =
false;
8864 if (IsScalarToVector)
8871 bool ReverseVEXT =
false;
8873 if (ST->hasNEON() &&
isVEXTMask(ShuffleMask, VT, ReverseVEXT, Imm)) {
8897 unsigned WhichResult = 0;
8898 bool isV_UNDEF =
false;
8899 if (ST->hasNEON()) {
8901 ShuffleMask, VT, WhichResult, isV_UNDEF)) {
8908 if (ST->hasMVEIntegerOps()) {
8943 }) &&
"Unexpected shuffle index into UNDEF operand!");
8946 ShuffleMask, SubVT, WhichResult, isV_UNDEF)) {
8949 assert((WhichResult == 0) &&
8950 "In-place shuffle of concat can only have one result!");
8959 if (ST->hasMVEIntegerOps() && EltSize <= 32) {
8963 for (
bool Top : {
false,
true}) {
8964 for (
bool SingleSource : {
false,
true}) {
8965 if (
isTruncMask(ShuffleMask, VT, Top, SingleSource)) {
8970 SingleSource ? V1 : V2);
8986 unsigned PFIndexes[4];
8987 for (
unsigned i = 0; i != 4; ++i) {
8988 if (ShuffleMask[i] < 0)
8991 PFIndexes[i] = ShuffleMask[i];
8995 unsigned PFTableIndex =
8996 PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3];
8998 unsigned Cost = (PFEntry >> 30);
9004 unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1);
9005 unsigned RHSID = (PFEntry >> 0) & ((1 << 13)-1);
9015 if (EltSize >= 32) {
9023 for (
unsigned i = 0; i < NumElts; ++i) {
9024 if (ShuffleMask[i] < 0)
9028 ShuffleMask[i] < (
int)NumElts ? V1 : V2,
9036 if ((VT == MVT::v8i16 || VT == MVT::v8f16 || VT == MVT::v16i8) &&
9040 if (ST->hasNEON() && VT == MVT::v8i8)
9044 if (ST->hasMVEIntegerOps())
9053 EVT VecVT =
Op.getOperand(0).getValueType();
9056 assert(ST->hasMVEIntegerOps() &&
9057 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
9061 unsigned Lane =
Op.getConstantOperandVal(2);
9062 unsigned LaneWidth =
9064 unsigned Mask = ((1 << LaneWidth) - 1) << Lane * LaneWidth;
9076 if (!isa<ConstantSDNode>(Lane))
9082 if (Subtarget->hasMVEIntegerOps() &&
9083 Op.getValueType().getScalarSizeInBits() == 1)
9107 IVecIn, IElt, Lane);
9116 EVT VecVT =
Op.getOperand(0).getValueType();
9119 assert(ST->hasMVEIntegerOps() &&
9120 "LowerINSERT_VECTOR_ELT_i1 called without MVE!");
9124 unsigned Lane =
Op.getConstantOperandVal(1);
9125 unsigned LaneWidth =
9136 if (!isa<ConstantSDNode>(Lane))
9156 assert(
Op.getValueType().getScalarSizeInBits() == 1 &&
9157 "Unexpected custom CONCAT_VECTORS lowering");
9159 "Unexpected custom CONCAT_VECTORS lowering");
9160 assert(ST->hasMVEIntegerOps() &&
9161 "CONCAT_VECTORS lowering only supported for MVE");
9165 EVT Op2VT = V2.getValueType();
9166 assert(Op1VT == Op2VT &&
"Operand types don't match!");
9167 assert((Op1VT == MVT::v2i1 || Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) &&
9168 "Unexpected i1 concat operations!");
9181 if (Op1VT == MVT::v4i1 || Op1VT == MVT::v8i1) {
9195 auto ExtractInto = [&DAG, &dl](
SDValue NewV,
SDValue ConVec,
unsigned &j) {
9196 EVT NewVT = NewV.getValueType();
9197 EVT ConcatVT = ConVec.getValueType();
9198 unsigned ExtScale = 1;
9199 if (NewVT == MVT::v2f64) {
9213 ConVec = ExtractInto(NewV1, ConVec, j);
9214 ConVec = ExtractInto(NewV2, ConVec, j);
9224 while (ConcatOps.
size() > 1) {
9225 for (
unsigned I = 0, E = ConcatOps.
size();
I != E;
I += 2) {
9228 ConcatOps[
I / 2] = ConcatPair(V1, V2);
9232 return ConcatOps[0];
9237 EVT VT =
Op->getValueType(0);
9244 "unexpected CONCAT_VECTORS");
9265 EVT VT =
Op.getValueType();
9268 unsigned Index = V2->getAsZExtVal();
9271 "Unexpected custom EXTRACT_SUBVECTOR lowering");
9272 assert(ST->hasMVEIntegerOps() &&
9273 "EXTRACT_SUBVECTOR lowering only supported for MVE");
9283 EVT SubVT = MVT::v4i32;
9285 for (
unsigned i =
Index, j = 0; i < (
Index + NumElts); i++, j += 2) {
9300 for (
unsigned i =
Index, j = 0; i < (
Index + NumElts); i++, j++) {
9316 assert(ST->hasMVEIntegerOps() &&
"Expected MVE!");
9317 EVT VT =
N->getValueType(0);
9318 assert((VT == MVT::v16i1 || VT == MVT::v8i1 || VT == MVT::v4i1) &&
9319 "Expected a vector i1 type!");
9321 EVT FromVT =
Op.getValueType();
9332 if (!Subtarget->hasMVEIntegerOps())
9335 EVT ToVT =
N->getValueType(0);
9378 if (ToVT != MVT::v8i16 && ToVT != MVT::v16i8)
9380 EVT FromVT =
N->getOperand(0).getValueType();
9381 if (FromVT != MVT::v8i32 && FromVT != MVT::v16i16)
9392 if (!Subtarget->hasMVEIntegerOps())
9397 EVT ToVT =
N->getValueType(0);
9398 if (ToVT != MVT::v16i32 && ToVT != MVT::v8i32 && ToVT != MVT::v16i16)
9401 EVT FromVT =
Op.getValueType();
9402 if (FromVT != MVT::v8i16 && FromVT != MVT::v16i8)
9413 SDValue Ext1 = Ext.getValue(1);
9416 Ext = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext);
9417 Ext1 = DAG.
getNode(
N->getOpcode(),
DL, MVT::v8i32, Ext1);
9429 EVT VT =
N->getValueType(0);
9431 SDNode *BVN =
N->getOperand(0).getNode();
9436 unsigned HiElt = 1 - LoElt;
9441 if (!Lo0 || !Hi0 || !Lo1 || !Hi1)
9457 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
9458 SDNode *Elt =
N->getOperand(i).getNode();
9461 unsigned HalfSize = EltSize / 2;
9463 if (!
isIntN(HalfSize,
C->getSExtValue()))
9466 if (!
isUIntN(HalfSize,
C->getZExtValue()))
9505 switch (OrigSimpleTy) {
9521 unsigned ExtOpcode) {
9544 if (ExtendedTy == LD->getMemoryVT())
9545 return DAG.
getLoad(LD->getMemoryVT(),
SDLoc(LD), LD->getChain(),
9546 LD->getBasePtr(), LD->getPointerInfo(), LD->getAlign(),
9547 LD->getMemOperand()->getFlags());
9553 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
9554 LD->getMemoryVT(), LD->getAlign(),
9555 LD->getMemOperand()->getFlags());
9568 N->getOperand(0)->getValueType(0),
9574 "Expected extending load");
9580 DAG.
getNode(Opcode,
SDLoc(newLoad), LD->getValueType(0), newLoad);
9589 SDNode *BVN =
N->getOperand(0).getNode();
9591 BVN->
getValueType(0) == MVT::v4i32 &&
"expected v4i32 BUILD_VECTOR");
9599 EVT VT =
N->getValueType(0);
9605 for (
unsigned i = 0; i != NumElts; ++i) {
9606 const APInt &CInt =
N->getConstantOperandAPInt(i);
9615 unsigned Opcode =
N->getOpcode();
9617 SDNode *N0 =
N->getOperand(0).getNode();
9618 SDNode *N1 =
N->getOperand(1).getNode();
9626 unsigned Opcode =
N->getOpcode();
9628 SDNode *N0 =
N->getOperand(0).getNode();
9629 SDNode *N1 =
N->getOperand(1).getNode();
9639 EVT VT =
Op.getValueType();
9641 "unexpected type for custom-lowering ISD::MUL");
9642 SDNode *N0 =
Op.getOperand(0).getNode();
9643 SDNode *N1 =
Op.getOperand(1).getNode();
9644 unsigned NewOpc = 0;
9648 if (isN0SExt && isN1SExt)
9653 if (isN0ZExt && isN1ZExt)
9655 else if (isN1SExt || isN1ZExt) {
9672 if (VT == MVT::v2i64)
9689 "unexpected types for extended operands to VMULL");
9690 return DAG.
getNode(NewOpc,
DL, VT, Op0, Op1);
9725 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9759 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9762 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9783 EVT VT =
Op.getValueType();
9784 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9785 "unexpected type for custom-lowering ISD::SDIV");
9792 if (VT == MVT::v8i8) {
9820 EVT VT =
Op.getValueType();
9821 assert((VT == MVT::v4i16 || VT == MVT::v8i8) &&
9822 "unexpected type for custom-lowering ISD::UDIV");
9829 if (VT == MVT::v8i8) {
9868 DAG.
getConstant(Intrinsic::arm_neon_vrecpe, dl, MVT::i32),
9871 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9875 DAG.
getConstant(Intrinsic::arm_neon_vrecps, dl, MVT::i32),
9896 EVT VT =
N->getValueType(0);
9910 Op.getOperand(1), Carry);
9924 Op.getOperand(1), Carry);
9957 bool ShouldUseSRet = Subtarget->
isAPCS_ABI();
9959 if (ShouldUseSRet) {
9969 Entry.IsSExt =
false;
9970 Entry.IsZExt =
false;
9971 Entry.IsSRet =
true;
9972 Args.push_back(Entry);
9979 Entry.IsSExt =
false;
9980 Entry.IsZExt =
false;
9981 Args.push_back(Entry);
9984 (ArgVT == MVT::f64) ? RTLIB::SINCOS_STRET_F64 : RTLIB::SINCOS_STRET_F32;
9994 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
9997 return CallResult.first;
10016 EVT VT =
Op.getValueType();
10017 assert((VT == MVT::i32 || VT == MVT::i64) &&
10018 "unexpected type for custom lowering DIV");
10024 const char *
Name =
nullptr;
10026 Name = (VT == MVT::i32) ?
"__rt_sdiv" :
"__rt_sdiv64";
10028 Name = (VT == MVT::i32) ?
"__rt_udiv" :
"__rt_udiv64";
10034 for (
auto AI : {1, 0}) {
10036 Arg.Node =
Op.getOperand(AI);
10037 Arg.Ty = Arg.Node.getValueType().getTypeForEVT(*DAG.
getContext());
10038 Args.push_back(Arg);
10041 CallLoweringInfo CLI(DAG);
10045 ES, std::move(Args));
10055ARMTargetLowering::BuildSDIVPow2(
SDNode *
N,
const APInt &Divisor,
10063 const bool MinSize =
ST.hasMinSize();
10064 const bool HasDivide =
ST.isThumb() ?
ST.hasDivideInThumbMode()
10065 :
ST.hasDivideInARMMode();
10069 if (
N->getOperand(0).getValueType().isVector())
10074 if (!(MinSize && HasDivide))
10087 if (Divisor.
sgt(128))
10095 assert(
Op.getValueType() == MVT::i32 &&
10096 "unexpected type for custom lowering DIV");
10102 return LowerWindowsDIVLibCall(
Op, DAG,
Signed, DBZCHK);
10108 if (
N->getValueType(0) == MVT::i32)
10116void ARMTargetLowering::ExpandDIV_Windows(
10122 assert(
Op.getValueType() == MVT::i64 &&
10123 "unexpected type for custom lowering DIV");
10140 EVT MemVT = LD->getMemoryVT();
10141 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10142 MemVT == MVT::v16i1) &&
10143 "Expected a predicate type!");
10144 assert(MemVT ==
Op.getValueType());
10146 "Expected a non-extending load");
10147 assert(LD->isUnindexed() &&
"Expected a unindexed load");
10161 ISD::EXTLOAD, dl, MVT::i32, LD->getChain(), LD->getBasePtr(),
10163 LD->getMemOperand());
10170 if (MemVT != MVT::v16i1)
10179 EVT MemVT =
LD->getMemoryVT();
10180 assert(
LD->isUnindexed() &&
"Loads should be unindexed at this point.");
10182 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10188 {LD->getChain(), LD->getBasePtr()}, MemVT,
LD->getMemOperand());
10198 EVT MemVT = ST->getMemoryVT();
10199 assert((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10200 MemVT == MVT::v16i1) &&
10201 "Expected a predicate type!");
10202 assert(MemVT == ST->getValue().getValueType());
10203 assert(!ST->isTruncatingStore() &&
"Expected a non-extending store");
10204 assert(ST->isUnindexed() &&
"Expected a unindexed store");
10209 SDValue Build = ST->getValue();
10210 if (MemVT != MVT::v16i1) {
10229 ST->getChain(), dl, GRP, ST->getBasePtr(),
10231 ST->getMemOperand());
10237 EVT MemVT = ST->getMemoryVT();
10238 assert(ST->isUnindexed() &&
"Stores should be unindexed at this point.");
10240 if (MemVT == MVT::i64 && Subtarget->hasV5TEOps() &&
10256 {ST->getChain(), Lo, Hi, ST->getBasePtr()},
10257 MemVT, ST->getMemOperand());
10258 }
else if (Subtarget->hasMVEIntegerOps() &&
10259 ((MemVT == MVT::v2i1 || MemVT == MVT::v4i1 || MemVT == MVT::v8i1 ||
10260 MemVT == MVT::v16i1))) {
10275 MVT VT =
Op.getSimpleValueType();
10277 SDValue PassThru =
N->getPassThru();
10288 VT, dl,
N->getChain(),
N->getBasePtr(),
N->getOffset(), Mask, ZeroVec,
10289 N->getMemoryVT(),
N->getMemOperand(),
N->getAddressingMode(),
10290 N->getExtensionType(),
N->isExpandingLoad());
10295 if (!PassThru.
isUndef() && !PassThruIsCastZero)
10302 if (!ST->hasMVEIntegerOps())
10306 unsigned BaseOpcode = 0;
10307 switch (
Op->getOpcode()) {
10323 unsigned NumActiveLanes = NumElts;
10325 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10326 NumActiveLanes == 2) &&
10327 "Only expected a power 2 vector size");
10331 while (NumActiveLanes > 4) {
10334 Op0 = DAG.
getNode(BaseOpcode, dl, VT, Op0, Rev);
10335 NumActiveLanes /= 2;
10339 if (NumActiveLanes == 4) {
10349 SDValue Res0 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10350 SDValue Res1 = DAG.
getNode(BaseOpcode, dl, EltVT, Ext2, Ext3,
Op->getFlags());
10351 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Res0, Res1,
Op->getFlags());
10357 Res = DAG.
getNode(BaseOpcode, dl, EltVT, Ext0, Ext1,
Op->getFlags());
10361 if (EltVT !=
Op->getValueType(0))
10368 if (!ST->hasMVEFloatOps())
10375 if (!ST->hasNEON())
10383 unsigned PairwiseIntrinsic = 0;
10384 switch (
Op->getOpcode()) {
10388 PairwiseIntrinsic = Intrinsic::arm_neon_vpminu;
10391 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxu;
10394 PairwiseIntrinsic = Intrinsic::arm_neon_vpmins;
10397 PairwiseIntrinsic = Intrinsic::arm_neon_vpmaxs;
10403 unsigned NumActiveLanes = NumElts;
10405 assert((NumActiveLanes == 16 || NumActiveLanes == 8 || NumActiveLanes == 4 ||
10406 NumActiveLanes == 2) &&
10407 "Only expected a power 2 vector size");
10413 VT =
Lo.getValueType();
10415 NumActiveLanes /= 2;
10419 while (NumActiveLanes > 1) {
10421 NumActiveLanes /= 2;
10428 if (EltVT !=
Op.getValueType()) {
10429 unsigned Extend = 0;
10430 switch (
Op->getOpcode()) {
10442 Res = DAG.
getNode(Extend, dl,
Op.getValueType(), Res);
10464 SDValue Ops[] = {
N->getOperand(0),
10474 DAG.
getVTList(MVT::i32, MVT::Other), Ops);
10481 SDLoc dl(V.getNode());
10482 auto [VLo, VHi] = DAG.
SplitScalar(V, dl, MVT::i32, MVT::i32);
10490 const SDValue Ops[] = { RegClass, VLo, SubReg0, VHi, SubReg1 };
10492 DAG.
getMachineNode(TargetOpcode::REG_SEQUENCE, dl, MVT::Untyped, Ops), 0);
10498 assert(
N->getValueType(0) == MVT::i64 &&
10499 "AtomicCmpSwap on types less than 64 should be legal");
10500 SDValue Ops[] = {
N->getOperand(1),
10505 ARM::CMP_SWAP_64,
SDLoc(
N),
10506 DAG.
getVTList(MVT::Untyped, MVT::i32, MVT::Other), Ops);
10525 EVT VT =
Op.getValueType();
10534 if (isUnsupportedFloatingType(
LHS.getValueType())) {
10536 DAG,
LHS.getValueType(), LHS, RHS,
CC, dl, LHS, RHS, Chain, IsSignaling);
10537 if (!
RHS.getNode()) {
10558 SDValue Cmp = getVFPCmp(LHS, RHS, DAG, dl, IsSignaling);
10559 SDValue Result = getCMOV(dl, VT, False, True, ARMcc, CCR, Cmp, DAG);
10561 ARMcc = DAG.
getConstant(CondCode2, dl, MVT::i32);
10562 Cmp = getVFPCmp(LHS, RHS, DAG, dl, IsSignaling);
10563 Result = getCMOV(dl, VT, Result, True, ARMcc, CCR, Cmp, DAG);
10579 switch (
Op.getOpcode()) {
10611 case ISD::BITCAST:
return ExpandBITCAST(
Op.getNode(), DAG, Subtarget);
10615 case ISD::SREM:
return LowerREM(
Op.getNode(), DAG);
10616 case ISD::UREM:
return LowerREM(
Op.getNode(), DAG);
10638 return LowerSET_FPMODE(
Op, DAG);
10640 return LowerRESET_FPMODE(
Op, DAG);
10644 return LowerDIV_Windows(
Op, DAG,
true);
10648 return LowerDIV_Windows(
Op, DAG,
false);
10655 return LowerSignedALUO(
Op, DAG);
10658 return LowerUnsignedALUO(
Op, DAG);
10692 return LowerDYNAMIC_STACKALLOC(
Op, DAG);
10701 return LowerSPONENTRY(
Op, DAG);
10708 unsigned IntNo =
N->getConstantOperandVal(0);
10710 if (IntNo == Intrinsic::arm_smlald)
10712 else if (IntNo == Intrinsic::arm_smlaldx)
10714 else if (IntNo == Intrinsic::arm_smlsld)
10716 else if (IntNo == Intrinsic::arm_smlsldx)
10723 std::tie(
Lo,
Hi) = DAG.
SplitScalar(
N->getOperand(3), dl, MVT::i32, MVT::i32);
10727 N->getOperand(1),
N->getOperand(2),
10739 switch (
N->getOpcode()) {
10746 Res = ExpandBITCAST(
N, DAG, Subtarget);
10755 Res = LowerREM(
N, DAG);
10759 Res = LowerDivRem(
SDValue(
N, 0), DAG);
10813 "ROPI/RWPI not currently supported with SjLj");
10822 bool isThumb = Subtarget->isThumb();
10823 bool isThumb2 = Subtarget->
isThumb2();
10826 unsigned PCAdj = (
isThumb || isThumb2) ? 4 : 8;
10832 : &ARM::GPRRegClass;
10850 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10856 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10862 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10880 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10885 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10890 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
10895 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
10901 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
10916 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
10922 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
10946 : &ARM::GPRnopcRegClass;
10951 unsigned MaxCSNum = 0;
10959 if (!
II.isEHLabel())
10963 if (!MF->hasCallSiteLandingPad(
Sym))
continue;
10966 for (
unsigned Idx : CallSiteIdxs) {
10967 CallSiteNumToLPad[
Idx].push_back(&BB);
10968 MaxCSNum = std::max(MaxCSNum,
Idx);
10975 std::vector<MachineBasicBlock*> LPadList;
10978 for (
unsigned I = 1;
I <= MaxCSNum; ++
I) {
10981 LPadList.push_back(
MBB);
10986 assert(!LPadList.empty() &&
10987 "No landing pad destinations for the dispatch jump table!");
11001 unsigned trap_opcode;
11002 if (Subtarget->isThumb())
11003 trap_opcode = ARM::tTRAP;
11005 trap_opcode = Subtarget->useNaClTrap() ? ARM::TRAPNaCl : ARM::TRAP;
11014 MF->insert(MF->end(), DispatchBB);
11015 MF->insert(MF->end(), DispContBB);
11016 MF->insert(MF->end(), TrapBB);
11020 SetupEntryBlockForSjLj(
MI,
MBB, DispatchBB, FI);
11027 MIB =
BuildMI(DispatchBB, dl,
TII->get(ARM::Int_eh_sjlj_dispatchsetup));
11039 unsigned NumLPads = LPadList.size();
11041 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11042 BuildMI(DispatchBB, dl,
TII->get(ARM::t2LDRi12), NewVReg1)
11048 if (NumLPads < 256) {
11049 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPri))
11051 .
addImm(LPadList.size())
11054 Register VReg1 =
MRI->createVirtualRegister(TRC);
11055 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVi16), VReg1)
11056 .
addImm(NumLPads & 0xFFFF)
11059 unsigned VReg2 = VReg1;
11060 if ((NumLPads & 0xFFFF0000) != 0) {
11061 VReg2 =
MRI->createVirtualRegister(TRC);
11062 BuildMI(DispatchBB, dl,
TII->get(ARM::t2MOVTi16), VReg2)
11068 BuildMI(DispatchBB, dl,
TII->get(ARM::t2CMPrr))
11074 BuildMI(DispatchBB, dl,
TII->get(ARM::t2Bcc))
11079 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11080 BuildMI(DispContBB, dl,
TII->get(ARM::t2LEApcrelJT), NewVReg3)
11084 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11085 BuildMI(DispContBB, dl,
TII->get(ARM::t2ADDrs), NewVReg4)
11092 BuildMI(DispContBB, dl,
TII->get(ARM::t2BR_JT))
11096 }
else if (Subtarget->isThumb()) {
11097 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11098 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRspi), NewVReg1)
11104 if (NumLPads < 256) {
11105 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPi8))
11112 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
11115 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
11118 Register VReg1 =
MRI->createVirtualRegister(TRC);
11119 BuildMI(DispatchBB, dl,
TII->get(ARM::tLDRpci))
11123 BuildMI(DispatchBB, dl,
TII->get(ARM::tCMPr))
11129 BuildMI(DispatchBB, dl,
TII->get(ARM::tBcc))
11134 Register NewVReg2 =
MRI->createVirtualRegister(TRC);
11135 BuildMI(DispContBB, dl,
TII->get(ARM::tLSLri), NewVReg2)
11141 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11142 BuildMI(DispContBB, dl,
TII->get(ARM::tLEApcrelJT), NewVReg3)
11146 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11147 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg4)
11157 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
11158 BuildMI(DispContBB, dl,
TII->get(ARM::tLDRi), NewVReg5)
11164 unsigned NewVReg6 = NewVReg5;
11165 if (IsPositionIndependent) {
11166 NewVReg6 =
MRI->createVirtualRegister(TRC);
11167 BuildMI(DispContBB, dl,
TII->get(ARM::tADDrr), NewVReg6)
11174 BuildMI(DispContBB, dl,
TII->get(ARM::tBR_JTr))
11178 Register NewVReg1 =
MRI->createVirtualRegister(TRC);
11179 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRi12), NewVReg1)
11185 if (NumLPads < 256) {
11186 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPri))
11190 }
else if (Subtarget->hasV6T2Ops() && isUInt<16>(NumLPads)) {
11191 Register VReg1 =
MRI->createVirtualRegister(TRC);
11192 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVi16), VReg1)
11193 .
addImm(NumLPads & 0xFFFF)
11196 unsigned VReg2 = VReg1;
11197 if ((NumLPads & 0xFFFF0000) != 0) {
11198 VReg2 =
MRI->createVirtualRegister(TRC);
11199 BuildMI(DispatchBB, dl,
TII->get(ARM::MOVTi16), VReg2)
11205 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11212 const Constant *
C = ConstantInt::get(Int32Ty, NumLPads);
11215 Align Alignment = MF->getDataLayout().getPrefTypeAlign(Int32Ty);
11218 Register VReg1 =
MRI->createVirtualRegister(TRC);
11219 BuildMI(DispatchBB, dl,
TII->get(ARM::LDRcp))
11224 BuildMI(DispatchBB, dl,
TII->get(ARM::CMPrr))
11235 Register NewVReg3 =
MRI->createVirtualRegister(TRC);
11236 BuildMI(DispContBB, dl,
TII->get(ARM::MOVsi), NewVReg3)
11241 Register NewVReg4 =
MRI->createVirtualRegister(TRC);
11242 BuildMI(DispContBB, dl,
TII->get(ARM::LEApcrelJT), NewVReg4)
11249 Register NewVReg5 =
MRI->createVirtualRegister(TRC);
11250 BuildMI(DispContBB, dl,
TII->get(ARM::LDRrs), NewVReg5)
11257 if (IsPositionIndependent) {
11258 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTadd))
11263 BuildMI(DispContBB, dl,
TII->get(ARM::BR_JTr))
11272 if (SeenMBBs.
insert(CurMBB).second)
11284 while (!Successors.empty()) {
11293 BB->normalizeSuccProbs();
11300 II = BB->rbegin(), IE = BB->rend();
II != IE; ++
II) {
11301 if (!
II->isCall())
continue;
11305 OI =
II->operands_begin(), OE =
II->operands_end();
11307 if (!OI->isReg())
continue;
11308 DefRegs[OI->getReg()] =
true;
11313 for (
unsigned i = 0; SavedRegs[i] != 0; ++i) {
11314 unsigned Reg = SavedRegs[i];
11316 !ARM::tGPRRegClass.contains(Reg) &&
11317 !ARM::hGPRRegClass.contains(Reg))
11319 if (Subtarget->
isThumb1Only() && !ARM::tGPRRegClass.contains(Reg))
11321 if (!Subtarget->isThumb() && !ARM::GPRRegClass.contains(Reg))
11334 MBBLPad->setIsEHPad(
false);
11337 MI.eraseFromParent();
11350static unsigned getLdOpcode(
unsigned LdSize,
bool IsThumb1,
bool IsThumb2) {
11352 return LdSize == 16 ? ARM::VLD1q32wb_fixed
11353 : LdSize == 8 ? ARM::VLD1d32wb_fixed : 0;
11355 return LdSize == 4 ? ARM::tLDRi
11356 : LdSize == 2 ? ARM::tLDRHi
11357 : LdSize == 1 ? ARM::tLDRBi : 0;
11359 return LdSize == 4 ? ARM::t2LDR_POST
11360 : LdSize == 2 ? ARM::t2LDRH_POST
11361 : LdSize == 1 ? ARM::t2LDRB_POST : 0;
11362 return LdSize == 4 ? ARM::LDR_POST_IMM
11363 : LdSize == 2 ? ARM::LDRH_POST
11364 : LdSize == 1 ? ARM::LDRB_POST_IMM : 0;
11369static unsigned getStOpcode(
unsigned StSize,
bool IsThumb1,
bool IsThumb2) {
11371 return StSize == 16 ? ARM::VST1q32wb_fixed
11372 : StSize == 8 ? ARM::VST1d32wb_fixed : 0;
11374 return StSize == 4 ? ARM::tSTRi
11375 : StSize == 2 ? ARM::tSTRHi
11376 : StSize == 1 ? ARM::tSTRBi : 0;
11378 return StSize == 4 ? ARM::t2STR_POST
11379 : StSize == 2 ? ARM::t2STRH_POST
11380 : StSize == 1 ? ARM::t2STRB_POST : 0;
11381 return StSize == 4 ? ARM::STR_POST_IMM
11382 : StSize == 2 ? ARM::STRH_POST
11383 : StSize == 1 ? ARM::STRB_POST_IMM : 0;
11390 unsigned LdSize,
unsigned Data,
unsigned AddrIn,
11391 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11392 unsigned LdOpc =
getLdOpcode(LdSize, IsThumb1, IsThumb2);
11393 assert(LdOpc != 0 &&
"Should have a load opcode");
11400 }
else if (IsThumb1) {
11406 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11411 }
else if (IsThumb2) {
11431 unsigned StSize,
unsigned Data,
unsigned AddrIn,
11432 unsigned AddrOut,
bool IsThumb1,
bool IsThumb2) {
11433 unsigned StOpc =
getStOpcode(StSize, IsThumb1, IsThumb2);
11434 assert(StOpc != 0 &&
"Should have a store opcode");
11436 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11441 }
else if (IsThumb1) {
11448 BuildMI(*BB, Pos, dl,
TII->get(ARM::tADDi8), AddrOut)
11453 }
else if (IsThumb2) {
11454 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11460 BuildMI(*BB, Pos, dl,
TII->get(StOpc), AddrOut)
11481 unsigned SizeVal =
MI.getOperand(2).getImm();
11482 unsigned Alignment =
MI.getOperand(3).getImm();
11487 unsigned UnitSize = 0;
11492 bool IsThumb2 = Subtarget->
isThumb2();
11493 bool IsThumb = Subtarget->isThumb();
11495 if (Alignment & 1) {
11497 }
else if (Alignment & 2) {
11502 Subtarget->hasNEON()) {
11503 if ((Alignment % 16 == 0) && SizeVal >= 16)
11505 else if ((Alignment % 8 == 0) && SizeVal >= 8)
11514 bool IsNeon = UnitSize >= 8;
11515 TRC = IsThumb ? &ARM::tGPRRegClass : &ARM::GPRRegClass;
11517 VecTRC = UnitSize == 16 ? &ARM::DPairRegClass
11518 : UnitSize == 8 ? &ARM::DPRRegClass
11521 unsigned BytesLeft = SizeVal % UnitSize;
11522 unsigned LoopSize = SizeVal - BytesLeft;
11524 if (SizeVal <= Subtarget->getMaxInlineSizeThreshold()) {
11528 unsigned srcIn = src;
11529 unsigned destIn = dest;
11530 for (
unsigned i = 0; i < LoopSize; i+=UnitSize) {
11531 Register srcOut =
MRI.createVirtualRegister(TRC);
11532 Register destOut =
MRI.createVirtualRegister(TRC);
11533 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11535 IsThumb1, IsThumb2);
11537 IsThumb1, IsThumb2);
11545 for (
unsigned i = 0; i < BytesLeft; i++) {
11546 Register srcOut =
MRI.createVirtualRegister(TRC);
11547 Register destOut =
MRI.createVirtualRegister(TRC);
11548 Register scratch =
MRI.createVirtualRegister(TRC);
11550 IsThumb1, IsThumb2);
11552 IsThumb1, IsThumb2);
11556 MI.eraseFromParent();
11582 MF->
insert(It, loopMBB);
11583 MF->
insert(It, exitMBB);
11586 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
11596 Register varEnd =
MRI.createVirtualRegister(TRC);
11598 BuildMI(BB, dl,
TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
11601 }
else if (Subtarget->genExecuteOnly()) {
11602 assert(IsThumb &&
"Non-thumb expected to have used movt");
11607 const Constant *
C = ConstantInt::get(Int32Ty, LoopSize);
11638 Register varLoop =
MRI.createVirtualRegister(TRC);
11639 Register varPhi =
MRI.createVirtualRegister(TRC);
11640 Register srcLoop =
MRI.createVirtualRegister(TRC);
11641 Register srcPhi =
MRI.createVirtualRegister(TRC);
11642 Register destLoop =
MRI.createVirtualRegister(TRC);
11643 Register destPhi =
MRI.createVirtualRegister(TRC);
11651 BuildMI(BB, dl,
TII->get(ARM::PHI), destPhi)
11657 Register scratch =
MRI.createVirtualRegister(IsNeon ? VecTRC : TRC);
11659 IsThumb1, IsThumb2);
11661 IsThumb1, IsThumb2);
11665 BuildMI(*BB, BB->
end(), dl,
TII->get(ARM::tSUBi8), varLoop)
11673 TII->get(IsThumb2 ? ARM::t2SUBri : ARM::SUBri), varLoop);
11682 TII->get(IsThumb1 ? ARM::tBcc : IsThumb2 ? ARM::t2Bcc : ARM::Bcc))
11691 auto StartOfExit = exitMBB->
begin();
11695 unsigned srcIn = srcLoop;
11696 unsigned destIn = destLoop;
11697 for (
unsigned i = 0; i < BytesLeft; i++) {
11698 Register srcOut =
MRI.createVirtualRegister(TRC);
11699 Register destOut =
MRI.createVirtualRegister(TRC);
11700 Register scratch =
MRI.createVirtualRegister(TRC);
11701 emitPostLd(BB, StartOfExit,
TII, dl, 1, scratch, srcIn, srcOut,
11702 IsThumb1, IsThumb2);
11703 emitPostSt(BB, StartOfExit,
TII, dl, 1, scratch, destIn, destOut,
11704 IsThumb1, IsThumb2);
11709 MI.eraseFromParent();
11721 "__chkstk is only supported on Windows");
11722 assert(Subtarget->
isThumb2() &&
"Windows on ARM requires Thumb-2 mode");
11742 switch (
TM.getCodeModel()) {
11784 MI.eraseFromParent();
11808 .
addReg(
MI.getOperand(0).getReg())
11816 MI.eraseFromParent();
11840 if (miI == BB->
end()) {
11842 if (Succ->isLiveIn(ARM::CPSR))
11848 SelectItr->addRegisterKilled(ARM::CPSR,
TRI);
11860 Register AddDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11861 BuildMI(TpEntry, Dl,
TII->get(ARM::t2ADDri), AddDestReg)
11867 Register LsrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11868 BuildMI(TpEntry, Dl,
TII->get(ARM::t2LSRri), LsrDestReg)
11874 Register TotalIterationsReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11875 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopSetup), TotalIterationsReg)
11878 BuildMI(TpEntry, Dl,
TII->get(ARM::t2WhileLoopStart))
11879 .
addUse(TotalIterationsReg)
11886 return TotalIterationsReg;
11897 Register TotalIterationsReg,
bool IsMemcpy) {
11904 SrcPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11905 CurrSrcReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11906 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), SrcPhiReg)
11914 Register DestPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11915 Register CurrDestReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11916 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), DestPhiReg)
11923 Register LoopCounterPhiReg =
MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11924 Register RemainingLoopIterationsReg =
11925 MRI.createVirtualRegister(&ARM::GPRlrRegClass);
11926 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), LoopCounterPhiReg)
11927 .
addUse(TotalIterationsReg)
11929 .
addUse(RemainingLoopIterationsReg)
11933 Register PredCounterPhiReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11934 Register RemainingElementsReg =
MRI.createVirtualRegister(&ARM::rGPRRegClass);
11935 BuildMI(TpLoopBody, Dl,
TII->get(ARM::PHI), PredCounterPhiReg)
11936 .
addUse(ElementCountReg)
11938 .
addUse(RemainingElementsReg)
11942 Register VccrReg =
MRI.createVirtualRegister(&ARM::VCCRRegClass);
11943 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VCTP8), VccrReg)
11944 .
addUse(PredCounterPhiReg)
11949 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2SUBri), RemainingElementsReg)
11950 .
addUse(PredCounterPhiReg)
11958 SrcValueReg =
MRI.createVirtualRegister(&ARM::MQPRRegClass);
11959 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VLDRBU8_post))
11968 SrcValueReg = OpSrcReg;
11970 BuildMI(TpLoopBody, Dl,
TII->get(ARM::MVE_VSTRBU8_post))
11981 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopDec), RemainingLoopIterationsReg)
11982 .
addUse(LoopCounterPhiReg)
11985 BuildMI(TpLoopBody, Dl,
TII->get(ARM::t2LoopEnd))
11986 .
addUse(RemainingLoopIterationsReg)
11999 bool isThumb2 = Subtarget->
isThumb2();
12000 switch (
MI.getOpcode()) {
12007 case ARM::tLDR_postidx: {
12011 .
add(
MI.getOperand(2))
12012 .
add(
MI.getOperand(3))
12013 .
add(
MI.getOperand(4))
12014 .
add(
MI.getOperand(0))
12016 MI.eraseFromParent();
12020 case ARM::MVE_MEMCPYLOOPINST:
12021 case ARM::MVE_MEMSETLOOPINST: {
12051 Register OpDestReg =
MI.getOperand(0).getReg();
12052 Register OpSrcReg =
MI.getOperand(1).getReg();
12053 Register OpSizeReg =
MI.getOperand(2).getReg();
12073 if (TpExit == BB) {
12075 "block containing memcpy/memset Pseudo");
12088 bool IsMemcpy =
MI.getOpcode() == ARM::MVE_MEMCPYLOOPINST;
12090 OpDestReg, OpSizeReg, TotalIterationsReg, IsMemcpy);
12105 MI.eraseFromParent();
12115 case ARM::t2STR_preidx:
12116 MI.setDesc(
TII->get(ARM::t2STR_PRE));
12118 case ARM::t2STRB_preidx:
12119 MI.setDesc(
TII->get(ARM::t2STRB_PRE));
12121 case ARM::t2STRH_preidx:
12122 MI.setDesc(
TII->get(ARM::t2STRH_PRE));
12125 case ARM::STRi_preidx:
12126 case ARM::STRBi_preidx: {
12127 unsigned NewOpc =
MI.getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM
12128 : ARM::STRB_PRE_IMM;
12130 unsigned Offset =
MI.getOperand(4).getImm();
12138 .
add(
MI.getOperand(0))
12139 .
add(
MI.getOperand(1))
12140 .
add(
MI.getOperand(2))
12142 .
add(
MI.getOperand(5))
12143 .
add(
MI.getOperand(6))
12145 MI.eraseFromParent();
12148 case ARM::STRr_preidx:
12149 case ARM::STRBr_preidx:
12150 case ARM::STRH_preidx: {
12152 switch (
MI.getOpcode()) {
12154 case ARM::STRr_preidx: NewOpc = ARM::STR_PRE_REG;
break;
12155 case ARM::STRBr_preidx: NewOpc = ARM::STRB_PRE_REG;
break;
12156 case ARM::STRH_preidx: NewOpc = ARM::STRH_PRE;
break;
12161 MI.eraseFromParent();
12165 case ARM::tMOVCCr_pseudo: {
12183 F->insert(It, copy0MBB);
12184 F->insert(It, sinkMBB);
12187 unsigned CallFrameSize =
TII->getCallFrameSizeAt(
MI);
12193 if (!
MI.killsRegister(ARM::CPSR,
nullptr) &&
12209 .
addImm(
MI.getOperand(3).getImm())
12210 .
addReg(
MI.getOperand(4).getReg());
12225 .
addReg(
MI.getOperand(1).getReg())
12227 .
addReg(
MI.getOperand(2).getReg())
12230 MI.eraseFromParent();
12235 case ARM::BCCZi64: {
12241 bool RHSisZero =
MI.getOpcode() == ARM::BCCZi64;
12246 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12250 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12256 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12260 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
12270 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
12279 MI.eraseFromParent();
12283 case ARM::Int_eh_sjlj_setjmp:
12284 case ARM::Int_eh_sjlj_setjmp_nofp:
12285 case ARM::tInt_eh_sjlj_setjmp:
12286 case ARM::t2Int_eh_sjlj_setjmp:
12287 case ARM::t2Int_eh_sjlj_setjmp_nofp:
12290 case ARM::Int_eh_sjlj_setup_dispatch:
12291 EmitSjLjDispatchBlock(
MI, BB);
12314 Fn->
insert(BBI, SinkBB);
12316 Register ABSSrcReg =
MI.getOperand(1).getReg();
12317 Register ABSDstReg =
MI.getOperand(0).getReg();
12318 bool ABSSrcKIll =
MI.getOperand(1).isKill();
12319 bool isThumb2 = Subtarget->
isThumb2();
12323 Register NewRsbDstReg =
MRI.createVirtualRegister(
12324 isThumb2 ? &ARM::rGPRRegClass : &ARM::GPRRegClass);
12338 BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
12345 TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc)).
addMBB(SinkBB)
12352 TII->get(isThumb2 ? ARM::t2RSBri : ARM::RSBri), NewRsbDstReg)
12361 TII->get(ARM::PHI), ABSDstReg)
12366 MI.eraseFromParent();
12371 case ARM::COPY_STRUCT_BYVAL_I32:
12373 return EmitStructByval(
MI, BB);
12374 case ARM::WIN__CHKSTK:
12375 return EmitLowered__chkstk(
MI, BB);
12376 case ARM::WIN__DBZCHK:
12377 return EmitLowered__dbzchk(
MI, BB);
12394 if (!
Node->hasAnyUseOfValue(0)) {
12395 MI.getOperand(0).setIsDead(
true);
12397 if (!
Node->hasAnyUseOfValue(1)) {
12398 MI.getOperand(1).setIsDead(
true);
12402 for (
unsigned I = 0;
I !=
MI.getOperand(4).getImm(); ++
I) {
12403 Register TmpReg =
MRI.createVirtualRegister(isThumb1 ? &ARM::tGPRRegClass
12404 : &ARM::GPRRegClass);
12411 if (
MI.getOpcode() == ARM::MEMCPY) {
12429 MCID = &
TII->get(NewOpc);
12432 MI.getDesc().getNumOperands() + 5 -
MI.getDesc().getSize()
12433 &&
"converted opcode should be the same except for cc_out"
12434 " (and, on Thumb1, pred)");
12444 MI.addOperand(
MI.getOperand(1));
12445 MI.removeOperand(1);
12449 for (
unsigned i =
MI.getNumOperands(); i--;) {
12451 if (
op.isReg() &&
op.isUse()) {
12454 MI.tieOperands(DefIdx, i);
12468 if (!
MI.hasOptionalDef() || !MCID->
operands()[ccOutIdx].isOptionalDef()) {
12469 assert(!NewOpc &&
"Optional cc_out operand required");
12474 bool definesCPSR =
false;
12475 bool deadCPSR =
false;
12476 for (
unsigned i = MCID->
getNumOperands(), e =
MI.getNumOperands(); i != e;
12480 definesCPSR =
true;
12483 MI.removeOperand(i);
12487 if (!definesCPSR) {
12488 assert(!NewOpc &&
"Optional cc_out operand required");
12491 assert(deadCPSR == !Node->hasAnyUseOfValue(1) &&
"inconsistent dead flag");
12493 assert(!
MI.getOperand(ccOutIdx).getReg() &&
12494 "expect uninitialized optional cc_out operand");
12532 switch (
N->getOpcode()) {
12533 default:
return false;
12535 CC =
N->getOperand(0);
12557 EVT VT =
N->getValueType(0);
12558 CC =
N->getOperand(0);
12559 if (
CC.getValueType() != MVT::i1 ||
CC.getOpcode() !=
ISD::SETCC)
12605 EVT VT =
N->getValueType(0);
12608 bool SwapSelectOps;
12610 NonConstantVal, DAG))
12616 OtherOp, NonConstantVal);
12622 CCOp, TrueVal, FalseVal);
12646 if (
N->getOpcode() ==
ARMISD::VTRN &&
N->getValueType(0) == MVT::v2i32)
12661 if (!
N->getValueType(0).is64BitVector())
12669 EVT VT =
N->getValueType(0);
12708 EVT VT =
N->getValueType(0);
12714 Opcode = Intrinsic::arm_neon_vpaddls;
12716 Opcode = Intrinsic::arm_neon_vpaddlu;
12744 EVT VT =
N->getValueType(0);
12759 unsigned nextIndex = 0;
12827 return DAG.
getNode(ExtOp, dl, VT, tmp);
12858 if (SRA.getOpcode() !=
ISD::SRA) {
12864 if (
auto Const = dyn_cast<ConstantSDNode>(SRA.getOperand(1))) {
12865 if (Const->getZExtValue() != 31)
12870 if (SRA.getOperand(0) !=
Mul)
12874 SDLoc dl(AddcNode);
12875 unsigned Opcode = 0;
12881 Op0 =
Mul.getOperand(0);
12882 Op1 =
Mul.getOperand(1);
12885 Op0 =
Mul.getOperand(0);
12886 Op1 =
Mul.getOperand(1).getOperand(0);
12889 Op0 =
Mul.getOperand(0).getOperand(0);
12890 Op1 =
Mul.getOperand(1);
12893 Op0 =
Mul->getOperand(0).getOperand(0);
12894 Op1 =
Mul->getOperand(1).getOperand(0);
12903 SDValue HiMLALResult(SMLAL.getNode(), 1);
12904 SDValue LoMLALResult(SMLAL.getNode(), 0);
12910 SDValue resNode(AddcNode, 0);
12939 "Expect an ADDE or SUBE");
12943 "ADDE node has the wrong inputs");
12962 "Expect ADDC with two result values. First: i32");
12982 bool IsLeftOperandMUL =
false;
12987 IsLeftOperandMUL =
true;
12998 SDValue *LowAddSub =
nullptr;
13001 if ((AddeSubeOp0 != MULOp.
getValue(1)) && (AddeSubeOp1 != MULOp.
getValue(1)))
13004 if (IsLeftOperandMUL)
13005 HiAddSub = &AddeSubeOp1;
13007 HiAddSub = &AddeSubeOp0;
13012 if (AddcSubcOp0 == MULOp.
getValue(0)) {
13013 LoMul = &AddcSubcOp0;
13014 LowAddSub = &AddcSubcOp1;
13016 if (AddcSubcOp1 == MULOp.
getValue(0)) {
13017 LoMul = &AddcSubcOp1;
13018 LowAddSub = &AddcSubcOp0;
13026 if (AddcSubcNode == HiAddSub->getNode() ||
13042 if (Subtarget->hasV6Ops() && Subtarget->hasDSP() && Subtarget->
useMulOps() &&
13056 return SDValue(AddeSubeNode, 0);
13067 DAG.
getVTList(MVT::i32, MVT::i32), Ops);
13077 return SDValue(AddeSubeNode, 0);
13089 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13098 SDNode *UmlalNode =
nullptr;
13123 DAG.
getVTList(MVT::i32, MVT::i32), Ops);
13137 if (!Subtarget->hasV6Ops() || !Subtarget->hasDSP())
13142 SDNode* AddcNode =
N->getOperand(2).getNode();
13143 SDNode* AddeNode =
N->getOperand(3).getNode();
13151 {N->getOperand(0), N->getOperand(1),
13152 AddcNode->getOperand(0), AddcNode->getOperand(1)});
13176 int32_t imm =
C->getSExtValue();
13177 if (imm < 0 && imm > std::numeric_limits<int>::min()) {
13182 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
N->getOperand(0),
RHS);
13197 int64_t imm =
C->getSExtValue();
13208 return DAG.
getNode(Opcode,
DL,
N->getVTList(),
13209 N->getOperand(0),
RHS,
N->getOperand(2));
13221 if (!Subtarget->hasMVEIntegerOps())
13234 SetCC =
N->getOperand(0);
13237 CC = cast<CondCodeSDNode>(SetCC->
getOperand(2))->get();
13238 TrueVal =
N->getOperand(1);
13239 FalseVal =
N->getOperand(2);
13241 LHS =
N->getOperand(0);
13242 RHS =
N->getOperand(1);
13243 CC = cast<CondCodeSDNode>(
N->getOperand(4))->get();
13244 TrueVal =
N->getOperand(2);
13245 FalseVal =
N->getOperand(3);
13250 unsigned int Opcode = 0;
13279 switch (TrueVal->getOpcode()) {
13298 if (TrueVal !=
LHS || FalseVal !=
RHS)
13301 EVT LeftType =
LHS->getValueType(0);
13302 EVT RightType =
RHS->getValueType(0);
13305 if (LeftType != VectorScalarType || RightType != VectorScalarType)
13309 if (VectorScalarType != MVT::i32)
13317 if (VectorScalarType != MVT::i32)
13330 EVT VT =
N->getValueType(0);
13338 Shft =
N->getOperand(0);
13344 cast<CondCodeSDNode>(Cmp.getOperand(2))->get() !=
ISD::SETLT ||
13345 Cmp.getOperand(0) !=
N->getOperand(1) ||
13346 Cmp.getOperand(1) !=
N->getOperand(2))
13348 Shft =
N->getOperand(1);
13360 ScalarType = MVT::i8;
13363 case (1 << 15) - 1:
13364 ScalarType = MVT::i16;
13367 case (1ULL << 31) - 1:
13368 ScalarType = MVT::i32;
13399 unsigned LegalLanes = 128 / (ShftAmt + 1);
13423 for (
unsigned I = 0;
I < NumParts; ++
I) {
13440 if (!Subtarget->hasMVEIntegerOps())
13455 if (
N->getOperand(0).getOpcode() !=
ISD::XOR)
13465 if (!Const || !Const->isOne())
13483 EVT VT =
N->getValueType(0);
13485 if (!Subtarget->hasMVEIntegerOps() ||
13514 Opc = Intrinsic::arm_mve_vctp64;
13517 Opc = Intrinsic::arm_mve_vctp32;
13520 Opc = Intrinsic::arm_mve_vctp16;
13523 Opc = Intrinsic::arm_mve_vctp8;
13577 EVT VT =
N->getValueType(0);
13583 switch (
Op.getOpcode()) {
13600 !isa<ConstantSDNode>(N0) && N1->
hasOneUse()) {
13608 unsigned N0RedOp = 0;
13615 unsigned N1RedOp = 0;
13629 if (
SDValue R = DistrubuteAddAddVecReduce(N0, N1))
13631 if (
SDValue R = DistrubuteAddAddVecReduce(N1, N0))
13638 auto DistrubuteVecReduceLoad = [&](
SDValue N0,
SDValue N1,
bool IsForward) {
13652 LoadSDNode *Load0 = dyn_cast<LoadSDNode>(N0);
13653 LoadSDNode *Load1 = dyn_cast<LoadSDNode>(N1);
13662 if (!BaseLocDecomp0.getBase() ||
13663 BaseLocDecomp0.getBase() != BaseLocDecomp1.getBase() ||
13664 !BaseLocDecomp0.hasValidOffset() || !BaseLocDecomp1.hasValidOffset())
13666 if (BaseLocDecomp0.getOffset() < BaseLocDecomp1.getOffset())
13668 if (BaseLocDecomp0.getOffset() > BaseLocDecomp1.getOffset())
13678 if (IsBefore < 0) {
13681 }
else if (IsBefore > 0) {
13694 }
else if (IsForward && IsVecReduce(N0) && IsVecReduce(N1) &&
13704 if (!IsVecReduce(N0) || !IsVecReduce(N1))
13714 if (
SDValue R = DistrubuteVecReduceLoad(N0, N1,
true))
13716 if (
SDValue R = DistrubuteVecReduceLoad(N1, N0,
false))
13723 if (!Subtarget->hasMVEIntegerOps())
13729 EVT VT =
N->getValueType(0);
13734 if (VT != MVT::i64)
13745 auto MakeVecReduce = [&](
unsigned Opcode,
unsigned OpcodeA,
SDValue NA,
13763 std::tie(Ops[0], Ops[1]) = DAG.
SplitScalar(NA, dl, MVT::i32, MVT::i32);
13765 unsigned S = VecRed->
getOpcode() == OpcodeA ? 2 : 0;
13814 "Expected shift op");
13832 if (
auto *Const = dyn_cast<ConstantSDNode>(N1->
getOperand(1))) {
13833 if (Const->getAPIntValue().ult(256))
13836 Const->getAPIntValue().sgt(-256))
13852 (
N->getOperand(0).getOpcode() ==
ISD::SHL ||
13853 N->getOperand(0).getOpcode() ==
ISD::SRL) &&
13854 "Expected XOR(SHIFT) pattern");
13857 auto *XorC = dyn_cast<ConstantSDNode>(
N->getOperand(1));
13858 auto *ShiftC = dyn_cast<ConstantSDNode>(
N->getOperand(0).getOperand(1));
13859 if (XorC && ShiftC) {
13860 unsigned MaskIdx, MaskLen;
13861 if (XorC->getAPIntValue().isShiftedMask(MaskIdx, MaskLen)) {
13862 unsigned ShiftAmt = ShiftC->getZExtValue();
13863 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
13864 if (
N->getOperand(0).getOpcode() ==
ISD::SHL)
13865 return MaskIdx == ShiftAmt && MaskLen == (
BitWidth - ShiftAmt);
13866 return MaskIdx == 0 && MaskLen == (
BitWidth - ShiftAmt);
13876 N->getOperand(0).getOpcode() ==
ISD::SRL) ||
13878 N->getOperand(0).getOpcode() ==
ISD::SHL)) &&
13879 "Expected shift-shift mask");
13892 return Subtarget->hasMVEIntegerOps() &&
isTypeLegal(VT);
13896 if (!Subtarget->hasNEON()) {
13915 return Subtarget->hasFP64();
13918 return Subtarget->hasMVEFloatOps();
13947 if (ST->isThumb() && ST->isThumb1Only())
13951 for (
auto *U :
N->uses()) {
13952 switch(U->getOpcode()) {
13965 if (isa<ConstantSDNode>(U->getOperand(0)) ||
13966 isa<ConstantSDNode>(U->getOperand(1)))
13970 if (U->getOperand(0).getOpcode() ==
ISD::SHL ||
13971 U->getOperand(1).getOpcode() ==
ISD::SHL)
13981 if (
N->getOperand(0).getOpcode() !=
ISD::SHL)
13986 auto *C1ShlC2 = dyn_cast<ConstantSDNode>(
N->getOperand(1));
13987 auto *C2 = dyn_cast<ConstantSDNode>(SHL.getOperand(1));
13988 if (!C1ShlC2 || !C2)
13991 APInt C2Int = C2->getAPIntValue();
13992 APInt C1Int = C1ShlC2->getAPIntValue();
13994 if (C2Int.
uge(C2Width))
14000 if ((C1Int & Mask) != C1Int)
14007 auto LargeImm = [](
const APInt &Imm) {
14008 unsigned Zeros = Imm.countl_zero() + Imm.countr_zero();
14009 return Imm.getBitWidth() - Zeros > 8;
14012 if (LargeImm(C1Int) || LargeImm(C2Int))
14024 SHL.dump();
N->dump());
14059 if (CSINC.getOpcode() !=
ARMISD::CSINC || !CSINC.hasOneUse())
14068 CSINC.getOperand(0)),
14069 CSINC.getOperand(1), CSINC.getOperand(2),
14070 CSINC.getOperand(3));
14089 if (!Subtarget->hasMVEIntegerOps() || !
N->getValueType(0).isVector())
14131 if (!Subtarget->hasVMLxForwarding())
14150 EVT VT =
N->getValueType(0);
14161 EVT VT =
N->getValueType(0);
14162 if (VT != MVT::v2i64)
14171 EVT VT = cast<VTSDNode>(
Op->getOperand(1))->getVT();
14173 return Op->getOperand(0);
14187 And =
And->getOperand(0);
14192 Mask = Mask->getOperand(0);
14195 Mask.getValueType() != MVT::v4i32)
14201 return And->getOperand(0);
14206 if (
SDValue Op0 = IsSignExt(N0)) {
14207 if (
SDValue Op1 = IsSignExt(N1)) {
14213 if (
SDValue Op0 = IsZeroExt(N0)) {
14214 if (
SDValue Op1 = IsZeroExt(N1)) {
14229 EVT VT =
N->getValueType(0);
14230 if (Subtarget->hasMVEIntegerOps() && VT == MVT::v2i64)
14241 if (VT != MVT::i32)
14248 int64_t MulAmt =
C->getSExtValue();
14249 unsigned ShiftAmt = llvm::countr_zero<uint64_t>(MulAmt);
14251 ShiftAmt = ShiftAmt & (32 - 1);
14256 MulAmt >>= ShiftAmt;
14259 if (llvm::has_single_bit<uint32_t>(MulAmt - 1)) {
14267 }
else if (llvm::has_single_bit<uint32_t>(MulAmt + 1)) {
14279 if (llvm::has_single_bit<uint32_t>(MulAmtAbs + 1)) {
14287 }
else if (llvm::has_single_bit<uint32_t>(MulAmtAbs - 1)) {
14317 if (
N->getValueType(0) != MVT::i32)
14326 if (C1 == 255 || C1 == 65535)
14329 SDNode *N0 =
N->getOperand(0).getNode();
14343 if (!C2 || C2 >= 32)
14387 if (Trailing == C2 && C2 + C3 < 32) {
14400 if (Leading == C2 && C2 + C3 < 32) {
14428 EVT VT =
N->getValueType(0);
14432 VT == MVT::v4i1 || VT == MVT::v8i1 || VT == MVT::v16i1)
14435 APInt SplatBits, SplatUndef;
14436 unsigned SplatBitSize;
14438 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14439 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14440 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14441 SplatBitSize == 64) {
14475 if (!Subtarget->hasV6Ops() ||
14476 (Subtarget->isThumb() &&
14477 (!Subtarget->hasThumb2() || !Subtarget->hasDSP())))
14480 SDValue SRL = OR->getOperand(0);
14481 SDValue SHL = OR->getOperand(1);
14484 SRL = OR->getOperand(1);
14485 SHL = OR->getOperand(0);
14492 if ((SRL.getOperand(0).getNode() != SHL.getOperand(0).getNode()) ||
14496 SDNode *SMULLOHI = SRL.getOperand(0).getNode();
14497 if (SRL.getOperand(0) !=
SDValue(SMULLOHI, 0) ||
14498 SHL.getOperand(0) !=
SDValue(SMULLOHI, 1))
14517 unsigned Opcode = 0;
14518 if (
isS16(OpS16, DAG))
14536 if (Subtarget->
isThumb1Only() || !Subtarget->hasV6T2Ops())
14539 EVT VT =
N->getValueType(0);
14554 if (VT != MVT::i32)
14567 if (Mask == 0xffff)
14574 if ((Val & ~Mask) != Val)
14599 (Mask == ~Mask2)) {
14602 if (Subtarget->hasDSP() &&
14603 (Mask == 0xffff || Mask == 0xffff0000))
14616 (~Mask == Mask2)) {
14619 if (Subtarget->hasDSP() &&
14620 (Mask2 == 0xffff || Mask2 == 0xffff0000))
14693 EVT VT =
N->getValueType(0);
14698 auto IsFreelyInvertable = [&](
SDValue V) {
14705 if (!(IsFreelyInvertable(N0) || IsFreelyInvertable(N1)))
14721 EVT VT =
N->getValueType(0);
14727 if (Subtarget->hasMVEIntegerOps() && (VT == MVT::v2i1 || VT == MVT::v4i1 ||
14728 VT == MVT::v8i1 || VT == MVT::v16i1))
14731 APInt SplatBits, SplatUndef;
14732 unsigned SplatBitSize;
14734 if (BVN && (Subtarget->hasNEON() || Subtarget->hasMVEIntegerOps()) &&
14735 BVN->
isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
14736 if (SplatBitSize == 8 || SplatBitSize == 16 || SplatBitSize == 32 ||
14737 SplatBitSize == 64) {
14773 unsigned SplatBitSize;
14776 APInt SplatBits0, SplatBits1;
14780 if (BVN0 && BVN0->
isConstantSplat(SplatBits0, SplatUndef, SplatBitSize,
14781 HasAnyUndefs) && !HasAnyUndefs) {
14782 if (BVN1 && BVN1->
isConstantSplat(SplatBits1, SplatUndef, SplatBitSize,
14783 HasAnyUndefs) && !HasAnyUndefs) {
14788 SplatBits0 == ~SplatBits1) {
14818 EVT VT =
N->getValueType(0);
14833 if (Subtarget->hasMVEIntegerOps()) {
14864 ToMask = ~N->getConstantOperandAPInt(2);
14870 isa<ConstantSDNode>(
From->getOperand(1))) {
14871 APInt Shift =
From->getConstantOperandAPInt(1);
14884 unsigned LastActiveBitInA =
A.countr_zero();
14885 unsigned FirstActiveBitInB =
B.getBitWidth() -
B.countl_zero() - 1;
14886 return LastActiveBitInA - 1 == FirstActiveBitInB;
14891 APInt ToMask, FromMask;
14899 APInt NewToMask, NewFromMask;
14901 if (NewFrom !=
From)
14905 if ((NewToMask & ToMask).getBoolValue())
14930 unsigned InvMask =
N->getConstantOperandVal(2);
14932 unsigned Width = llvm::bit_width<unsigned>(~InvMask) - LSB;
14934 static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
14935 "undefined behavior");
14936 unsigned Mask = (1u << Width) - 1;
14938 if ((Mask & (~Mask2)) == 0)
14940 N->getOperand(0), N1.
getOperand(0),
N->getOperand(2));
14947 APInt ToMask1, FromMask1;
14950 APInt ToMask2, FromMask2;
14956 APInt NewFromMask = FromMask1 | FromMask2;
14957 APInt NewToMask = ToMask1 | ToMask2;
14959 EVT VT =
N->getValueType(0);
14962 if (NewFromMask[0] == 0)
14974 APInt ToMask1 = ~N->getConstantOperandAPInt(2);
14975 APInt ToMask2 = ~N0.getConstantOperandAPInt(2);
14977 if (!N0.
hasOneUse() || (ToMask1 & ToMask2) != 0 ||
14981 EVT VT =
N->getValueType(0);
14984 N->getOperand(1),
N->getOperand(2));
14998 SDValue CSInc = Cmp->getOperand(0);
15048 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ)
15049 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15052 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
15054 N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
15067 SDValue InDouble =
N->getOperand(0);
15076 !cast<LoadSDNode>(InNode)->isVolatile()) {
15082 SDValue BasePtr = LD->getBasePtr();
15084 DAG.
getLoad(MVT::i32,
DL, LD->getChain(), BasePtr, LD->getPointerInfo(),
15085 LD->getAlign(), LD->getMemOperand()->getFlags());
15091 LD->getPointerInfo().getWithOffset(4),
15093 LD->getMemOperand()->getFlags());
15105 isa<ConstantSDNode>(InDouble.
getOperand(1))) {
15126 if (!Subtarget->
isLittle() && BVSwap)
15136 if (isa<ConstantSDNode>(BV.
getOperand(2))) {
15144 if (!Subtarget->
isLittle() && BVSwap)
15189 if (Copy.getValueType() == MVT::f32 &&
15191 bool HasGlue = Copy->getNumOperands() == 3;
15192 SDValue Ops[] = {Copy->getOperand(0), Copy->getOperand(1),
15193 HasGlue ? Copy->getOperand(2) :
SDValue()};
15194 EVT OutTys[] = {
N->getValueType(0), MVT::Other, MVT::Glue};
15212 if (
LoadSDNode *LN0 = dyn_cast<LoadSDNode>(Op0)) {
15213 if (LN0->hasOneUse() && LN0->isUnindexed() &&
15214 LN0->getMemoryVT() == MVT::i16) {
15217 LN0->getBasePtr(), LN0->getMemOperand());
15235 EVT VT =
N->getValueType(0);
15269 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
15270 for (
unsigned i = 0; i < NumElts; ++i) {
15271 SDNode *Elt =
N->getOperand(i).getNode();
15288 if (
N->getNumOperands() == 2)
15294 EVT VT =
N->getValueType(0);
15300 for (
unsigned i = 0; i < NumElts; ++i) {
15326 EVT VT =
N->getValueType(0);
15334 assert(EltVT == MVT::f32 &&
"Unexpected type!");
15339 Use->getValueType(0).isFloatingPoint())
15347 unsigned NumOfBitCastedElts = 0;
15349 unsigned NumOfRelevantElts = NumElts;
15350 for (
unsigned Idx = 0;
Idx < NumElts; ++
Idx) {
15355 ++NumOfBitCastedElts;
15356 }
else if (Elt.
isUndef() || isa<ConstantSDNode>(Elt))
15359 --NumOfRelevantElts;
15363 if (NumOfBitCastedElts <= NumOfRelevantElts / 2)
15381 for (
unsigned Idx = 0 ;
Idx < NumElts; ++
Idx) {
15386 V->getOperand(0).getValueType() == MVT::i32)
15388 V = V.getOperand(0);
15405 EVT VT =
N->getValueType(0);
15412 if (
Op->getOperand(0).getValueType() == VT)
15413 return Op->getOperand(0);
15428 if (
Op.getValueType() == MVT::i32) {
15439 EVT VT =
N->getValueType(0);
15444 if (ST->isLittle())
15454 if (
Op->getOperand(0).getValueType() == VT)
15455 return Op->getOperand(0);
15464 if (!Subtarget->hasMVEIntegerOps())
15467 EVT VT =
N->getValueType(0);
15498 EVT VT =
N->getValueType(0);
15499 SDNode *Elt =
N->getOperand(1).getNode();
15514 Vec, V,
N->getOperand(2));
15524 EVT VT =
N->getValueType(0);
15533 Ext.getOperand(0).getValueType() == MVT::f32)
15534 Ext = Ext.getOperand(0);
15536 !isa<ConstantSDNode>(Ext.getOperand(1)) ||
15537 Ext.getConstantOperandVal(1) % 2 != 0)
15539 if (Ext->use_size() == 1 &&
15544 SDValue Op0 = Ext.getOperand(0);
15547 unsigned Lane = Ext.getConstantOperandVal(1);
15553 return V->getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
15554 isa<ConstantSDNode>(V->getOperand(1)) &&
15555 V->getConstantOperandVal(1) == Lane + 1 &&
15556 V->getOperand(0).getResNo() == ResNo;
15558 if (OtherIt == Op0->
uses().end())
15563 SDValue OtherExt(*OtherIt, 0);
15576 DCI.
DAG.
getConstant(Ext.getConstantOperandVal(1) / 2, dl, MVT::i32));
15588 EVT VT =
N->getValueType(0);
15594 if (VT == MVT::f16 &&
X.getValueType() == MVT::i32)
15596 if (VT == MVT::i32 &&
X.getValueType() == MVT::f16)
15598 if (VT == MVT::f32 &&
X.getValueType() == MVT::i32)
15601 while (
X.getValueType() != VT &&
X->getOpcode() ==
ISD::BITCAST)
15602 X =
X->getOperand(0);
15603 if (
X.getValueType() == VT)
15609 isa<ConstantSDNode>(
N->getOperand(1)) &&
15611 return Op0.
getOperand(
N->getConstantOperandVal(1));
15616 isa<ConstantSDNode>(
N->getOperand(1)) &&
15621 unsigned Offset =
N->getConstantOperandVal(1);
15633 unsigned Idx =
N->getConstantOperandVal(1);
15647 EVT VT =
N->getValueType(0);
15651 cast<VTSDNode>(
N->getOperand(1))->getVT() ==
15652 Op.getOperand(0).getValueType().getScalarType())
15662 SDValue SubVec =
N->getOperand(1);
15663 uint64_t IdxVal =
N->getConstantOperandVal(2);
15674 if (IdxVal == 0 && Vec.
isUndef())
15680 (IdxVal != 0 && IdxVal != NumSubElts))
15753 EVT VT =
N->getValueType(0);
15764 unsigned HalfElts = NumElts/2;
15766 for (
unsigned n = 0; n < NumElts; ++n) {
15769 if (MaskElt < (
int)HalfElts)
15771 else if (MaskElt >= (
int)NumElts && MaskElt < (
int)(NumElts + HalfElts))
15772 NewElt = HalfElts + MaskElt - NumElts;
15799 bool SimpleConstIncOnly,
15807 bool isLoadOp =
true;
15808 bool isLaneOp =
false;
15811 bool hasAlignment =
true;
15812 unsigned NewOpc = 0;
15813 unsigned NumVecs = 0;
15814 if (
Target.isIntrinsic) {
15815 unsigned IntNo =
N->getConstantOperandVal(1);
15819 case Intrinsic::arm_neon_vld1:
15823 case Intrinsic::arm_neon_vld2:
15827 case Intrinsic::arm_neon_vld3:
15831 case Intrinsic::arm_neon_vld4:
15835 case Intrinsic::arm_neon_vld1x2:
15838 hasAlignment =
false;
15840 case Intrinsic::arm_neon_vld1x3:
15843 hasAlignment =
false;
15845 case Intrinsic::arm_neon_vld1x4:
15848 hasAlignment =
false;
15850 case Intrinsic::arm_neon_vld2dup:
15854 case Intrinsic::arm_neon_vld3dup:
15858 case Intrinsic::arm_neon_vld4dup:
15862 case Intrinsic::arm_neon_vld2lane:
15867 case Intrinsic::arm_neon_vld3lane:
15872 case Intrinsic::arm_neon_vld4lane:
15877 case Intrinsic::arm_neon_vst1:
15882 case Intrinsic::arm_neon_vst2:
15887 case Intrinsic::arm_neon_vst3:
15892 case Intrinsic::arm_neon_vst4:
15897 case Intrinsic::arm_neon_vst2lane:
15903 case Intrinsic::arm_neon_vst3lane:
15909 case Intrinsic::arm_neon_vst4lane:
15915 case Intrinsic::arm_neon_vst1x2:
15919 hasAlignment =
false;
15921 case Intrinsic::arm_neon_vst1x3:
15925 hasAlignment =
false;
15927 case Intrinsic::arm_neon_vst1x4:
15931 hasAlignment =
false;
15936 switch (
N->getOpcode()) {
15972 VecTy =
N->getValueType(0);
15973 }
else if (
Target.isIntrinsic) {
15974 VecTy =
N->getOperand(
Target.AddrOpIdx + 1).getValueType();
15977 "Node has to be a load, a store, or an intrinsic!");
15978 VecTy =
N->getOperand(1).getValueType();
15986 if (isLaneOp || isVLDDUPOp)
15989 if (NumBytes >= 3 * 16 &&
User.ConstInc != NumBytes) {
15995 if (SimpleConstIncOnly &&
User.ConstInc != NumBytes)
16001 EVT AlignedVecTy = VecTy;
16018 if (isa<LSBaseSDNode>(
N)) {
16021 assert(NumVecs == 1 &&
"Unexpected multi-element generic load/store.");
16022 assert(!isLaneOp &&
"Unexpected generic load/store lane.");
16033 Alignment =
Align(1);
16039 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16041 for (n = 0; n < NumResultVecs; ++n)
16042 Tys[n] = AlignedVecTy;
16043 Tys[n++] = MVT::i32;
16044 Tys[n] = MVT::Other;
16059 unsigned LastOperand =
16060 hasAlignment ?
N->getNumOperands() - 1 :
N->getNumOperands();
16061 for (
unsigned i =
Target.AddrOpIdx + 1; i < LastOperand; ++i)
16070 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::STORE) {
16081 for (
unsigned i = 0; i < NumResultVecs; ++i)
16086 if (AlignedVecTy != VecTy &&
N->getOpcode() ==
ISD::LOAD) {
16087 SDValue &LdVal = NewResults[0];
16123 switch (
N->getOpcode()) {
16126 if (isa<ConstantSDNode>(
N->getOperand(1))) {
16127 *
Ptr =
N->getOperand(0);
16128 *CInc =
N->getOperand(1);
16134 if (isa<ConstantSDNode>(
N->getOperand(2))) {
16135 *
Ptr =
N->getOperand(1);
16136 *CInc =
N->getOperand(2);
16171 const unsigned AddrOpIdx = ((isIntrinsic ||
isStore) ? 2 : 1);
16180 UE =
Addr.getNode()->use_end(); UI != UE; ++UI) {
16182 if (UI.getUse().getResNo() !=
Addr.getResNo() ||
16187 unsigned ConstInc =
16205 if (UI.getUse().getResNo() !=
Base.getResNo() ||
User ==
Addr.getNode() ||
16210 unsigned UserOffset =
16213 if (!UserOffset || UserOffset <=
Offset)
16216 unsigned NewConstInc = UserOffset -
Offset;
16226 unsigned NumValidUpd = BaseUpdates.
size();
16227 for (
unsigned I = 0;
I < NumValidUpd;) {
16231 std::swap(BaseUpdates[
I], BaseUpdates[NumValidUpd]);
16239 BaseUpdates.
resize(NumValidUpd);
16244 std::stable_sort(BaseUpdates.
begin(), BaseUpdates.
end(),
16246 return LHS.ConstInc < RHS.ConstInc;
16275 unsigned IntNo =
N->getConstantOperandVal(1);
16276 if (IntNo == Intrinsic::arm_mve_vst2q &&
N->getConstantOperandVal(5) != 1)
16278 if (IntNo == Intrinsic::arm_mve_vst4q &&
N->getConstantOperandVal(7) != 3)
16283 UE =
Addr.getNode()->use_end();
16287 UI.getUse().getResNo() !=
Addr.getResNo())
16303 bool isLoadOp =
true;
16304 unsigned NewOpc = 0;
16305 unsigned NumVecs = 0;
16309 case Intrinsic::arm_mve_vld2q:
16313 case Intrinsic::arm_mve_vld4q:
16317 case Intrinsic::arm_mve_vst2q:
16322 case Intrinsic::arm_mve_vst4q:
16332 VecTy =
N->getValueType(0);
16334 VecTy =
N->getOperand(3).getValueType();
16348 unsigned NumResultVecs = (isLoadOp ? NumVecs : 0);
16350 for (n = 0; n < NumResultVecs; ++n)
16352 Tys[n++] = MVT::i32;
16353 Tys[n] = MVT::Other;
16362 for (
unsigned i = 3; i <
N->getNumOperands(); ++i)
16370 for (
unsigned i = 0; i < NumResultVecs; ++i)
16389 EVT VT =
N->getValueType(0);
16395 SDNode *VLD =
N->getOperand(0).getNode();
16398 unsigned NumVecs = 0;
16399 unsigned NewOpc = 0;
16401 if (IntNo == Intrinsic::arm_neon_vld2lane) {
16404 }
else if (IntNo == Intrinsic::arm_neon_vld3lane) {
16407 }
else if (IntNo == Intrinsic::arm_neon_vld4lane) {
16420 if (UI.getUse().getResNo() == NumVecs)
16424 VLDLaneNo !=
User->getConstantOperandVal(1))
16431 for (n = 0; n < NumVecs; ++n)
16433 Tys[n] = MVT::Other;
16444 unsigned ResNo = UI.getUse().
getResNo();
16446 if (ResNo == NumVecs)
16454 std::vector<SDValue> VLDDupResults;
16455 for (
unsigned n = 0; n < NumVecs; ++n)
16469 EVT VT =
N->getValueType(0);
16472 if (Subtarget->hasMVEIntegerOps()) {
16476 ExtractVT = MVT::i32;
16478 N->getOperand(0),
N->getOperand(1));
16490 Op =
Op.getOperand(0);
16495 unsigned EltSize =
Op.getScalarValueSizeInBits();
16497 unsigned Imm =
Op.getConstantOperandVal(0);
16513 if (Subtarget->hasMVEIntegerOps()) {
16516 if (
Op.getValueType() == MVT::f32)
16519 else if (
Op.getValueType() == MVT::f16)
16524 if (!Subtarget->hasNEON())
16531 if (LD &&
Op.hasOneUse() && LD->isUnindexed() &&
16532 LD->getMemoryVT() ==
N->getValueType(0).getVectorElementType()) {
16533 SDValue Ops[] = {LD->getOperand(0), LD->getOperand(1),
16538 LD->getMemoryVT(), LD->getMemOperand());
16549 EVT VT =
N->getValueType(0);
16571 assert(StVT != VT &&
"Cannot truncate to the same type");
16581 if (0 != (NumElems * FromEltSz) % ToEltSz)
16584 unsigned SizeRatio = FromEltSz / ToEltSz;
16589 NumElems * SizeRatio);
16595 for (
unsigned i = 0; i < NumElems; ++i)
16609 MVT StoreType = MVT::i8;
16611 if (TLI.
isTypeLegal(Tp) && Tp.getSizeInBits() <= NumElems * ToEltSz)
16630 unsigned E = (ToEltSz * NumElems) / StoreType.
getSizeInBits();
16631 for (
unsigned I = 0;
I < E;
I++) {
16662 if (FromEltVT != MVT::f32 || ToEltVT != MVT::f16)
16665 unsigned NumElements = 4;
16682 unsigned Off0 = Rev ? NumElts : 0;
16683 unsigned Off1 = Rev ? 0 : NumElts;
16685 for (
unsigned I = 0;
I < NumElts;
I += 2) {
16686 if (M[
I] >= 0 && M[
I] != (
int)(Off0 +
I / 2))
16688 if (M[
I + 1] >= 0 && M[
I + 1] != (
int)(Off1 +
I / 2))
16695 if (
auto *Shuffle = dyn_cast<ShuffleVectorSDNode>(Trunc.
getOperand(0)))
16696 if (isVMOVNShuffle(Shuffle,
false) || isVMOVNShuffle(Shuffle,
true))
16716 unsigned NewOffset = i * NumElements * ToEltVT.
getSizeInBits() / 8;
16731 NewToVT, Alignment, MMOFlags, AAInfo);
16764 unsigned NewOffset =
16772 NewToVT, Alignment, MMOFlags, AAInfo);
16794 {Extract.getOperand(0), Extract.getOperand(1)});
16825 if (Subtarget->hasNEON())
16829 if (Subtarget->hasMVEFloatOps())
16833 if (Subtarget->hasMVEIntegerOps()) {
16909 if (!Subtarget->hasNEON())
16913 if (!
Op.getValueType().isVector() || !
Op.getValueType().isSimple() ||
16918 if (!isa<BuildVectorSDNode>(ConstVec))
16921 MVT FloatTy =
Op.getSimpleValueType().getVectorElementType();
16923 MVT IntTy =
N->getSimpleValueType(0).getVectorElementType();
16925 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
16926 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
16937 if (
C == -1 ||
C == 0 ||
C > 32)
16942 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
16943 Intrinsic::arm_neon_vcvtfp2fxu;
16946 DAG.
getConstant(IntrinsicOpcode, dl, MVT::i32),
Op->getOperand(0),
16949 if (IntBits < FloatBits)
16957 if (!Subtarget->hasMVEFloatOps())
16965 EVT VT =
N->getValueType(0);
16970 auto isIdentitySplat = [&](
SDValue Op,
bool NSZ) {
16974 uint64_t ImmVal =
Op.getOperand(0).getConstantOperandVal(0);
16975 if (VT == MVT::v4f32 && (ImmVal == 1664 || (ImmVal == 0 && NSZ)))
16977 if (VT == MVT::v8f16 && (ImmVal == 2688 || (ImmVal == 0 && NSZ)))
16990 if (!isIdentitySplat(Op1.
getOperand(2), NSZ))
17001 EVT VT =
N->getValueType(0);
17004 if (!
N->getFlags().hasAllowReassociation())
17011 unsigned Opc =
A.getConstantOperandVal(0);
17012 if (Opc != Intrinsic::arm_mve_vcmlaq)
17017 A.getOperand(3),
A.getOperand(4));
17049 if (!Subtarget->hasNEON())
17053 unsigned OpOpcode =
Op.getNode()->getOpcode();
17054 if (!
N->getValueType(0).isVector() || !
N->getValueType(0).isSimple() ||
17058 SDValue ConstVec =
N->getOperand(1);
17059 if (!isa<BuildVectorSDNode>(ConstVec))
17062 MVT FloatTy =
N->getSimpleValueType(0).getVectorElementType();
17064 MVT IntTy =
Op.getOperand(0).getSimpleValueType().getVectorElementType();
17066 unsigned NumLanes =
Op.getValueType().getVectorNumElements();
17067 if (FloatBits != 32 || IntBits > 32 || (NumLanes != 4 && NumLanes != 2)) {
17087 int32_t
C = IntVal.exactLogBase2();
17088 if (
C == -1 ||
C == 0 ||
C > 32)
17094 if (IntBits < FloatBits)
17096 NumLanes == 2 ? MVT::v2i32 : MVT::v4i32, ConvInput);
17098 unsigned IntrinsicOpcode =
isSigned ? Intrinsic::arm_neon_vcvtfxs2fp
17099 : Intrinsic::arm_neon_vcvtfxu2fp;
17107 if (!ST->hasMVEIntegerOps())
17111 EVT ResVT =
N->getValueType(0);
17139 EVT AVT =
A.getValueType();
17145 auto ExtendIfNeeded = [&](
SDValue A,
unsigned ExtendCode) {
17146 EVT AVT =
A.getValueType();
17158 if (ExtTypeMatches(
A, ExtTypes))
17159 return ExtendIfNeeded(
A, ExtendCode);
17162 auto IsPredVADDV = [&](
MVT RetTy,
unsigned ExtendCode,
17169 if (Ext->getOpcode() != ExtendCode)
17172 if (ExtTypeMatches(
A, ExtTypes))
17173 return ExtendIfNeeded(
A, ExtendCode);
17186 if (ResVT !=
RetTy)
17189 if (
Mul->getOpcode() == ExtendCode &&
17190 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17192 Mul =
Mul->getOperand(0);
17201 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17202 A = ExtendIfNeeded(
A, ExtendCode);
17203 B = ExtendIfNeeded(
B, ExtendCode);
17221 if (
Mul->getOpcode() == ExtendCode &&
17222 Mul->getOperand(0).getScalarValueSizeInBits() * 2 >=
17224 Mul =
Mul->getOperand(0);
17233 if (ExtTypeMatches(
A, ExtTypes) && ExtTypeMatches(
B, ExtTypes)) {
17234 A = ExtendIfNeeded(
A, ExtendCode);
17235 B = ExtendIfNeeded(
B, ExtendCode);
17246 EVT VT = Ops[0].getValueType();
17247 if (VT == MVT::v16i8) {
17249 "Unexpected illegal long reduction opcode");
17254 DAG.
getVTList(MVT::v8i16, MVT::v8i16), Ops[0]);
17257 DAG.
getVTList(MVT::v8i16, MVT::v8i16), Ops[1]);
17278 if (IsVMLAV(MVT::i64,
ISD::SIGN_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17281 if (IsVMLAV(MVT::i64,
ISD::ZERO_EXTEND, {MVT::v16i8, MVT::v8i16, MVT::v4i32},
17345 Op =
Op->getOperand(1);
17347 Op->getOperand(0)->getOpcode() ==
ISD::MUL) {
17349 if (
Mul->getOperand(0) ==
Mul->getOperand(1) &&
17366 unsigned VecOp =
N->getOperand(0).getValueType().isVector() ? 0 : 2;
17367 auto *Shuf = dyn_cast<ShuffleVectorSDNode>(
N->getOperand(VecOp));
17368 if (!Shuf || !Shuf->getOperand(1).isUndef())
17373 APInt SetElts(Mask.size(), 0);
17374 for (
int E : Mask) {
17375 if (E < 0 || E >= (
int)Mask.size())
17382 if (
N->getNumOperands() != VecOp + 1) {
17383 auto *Shuf2 = dyn_cast<ShuffleVectorSDNode>(
N->getOperand(VecOp + 1));
17384 if (!Shuf2 || !Shuf2->getOperand(1).isUndef() || Shuf2->getMask() != Mask)
17390 if (
Op.getValueType().isVector())
17402 unsigned IsTop =
N->getConstantOperandVal(2);
17409 if (Op0->
isUndef() && !IsTop)
17423 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17425 APInt Op0DemandedElts =
17426 IsTop ? Op1DemandedElts
17441 unsigned IsTop =
N->getConstantOperandVal(2);
17443 unsigned NumElts =
N->getValueType(0).getVectorNumElements();
17444 APInt Op0DemandedElts =
17456 EVT VT =
N->getValueType(0);
17460 auto *Shuf0 = dyn_cast<ShuffleVectorSDNode>(
LHS);
17461 auto *Shuf1 = dyn_cast<ShuffleVectorSDNode>(
RHS);
17463 if (Shuf0 && Shuf1 && Shuf0->getMask().equals(Shuf1->getMask()) &&
17464 LHS.getOperand(1).isUndef() &&
RHS.getOperand(1).isUndef() &&
17468 LHS.getOperand(0),
RHS.getOperand(0));
17482 if (
auto C = dyn_cast<ConstantSDNode>(
N->getOperand(2))) {
17483 int ShiftAmt =
C->getSExtValue();
17484 if (ShiftAmt == 0) {
17490 if (ShiftAmt >= -32 && ShiftAmt < 0) {
17491 unsigned NewOpcode =
17507 unsigned IntNo =
N->getConstantOperandVal(0);
17518 case Intrinsic::arm_neon_vshifts:
17519 case Intrinsic::arm_neon_vshiftu:
17520 case Intrinsic::arm_neon_vrshifts:
17521 case Intrinsic::arm_neon_vrshiftu:
17522 case Intrinsic::arm_neon_vrshiftn:
17523 case Intrinsic::arm_neon_vqshifts:
17524 case Intrinsic::arm_neon_vqshiftu:
17525 case Intrinsic::arm_neon_vqshiftsu:
17526 case Intrinsic::arm_neon_vqshiftns:
17527 case Intrinsic::arm_neon_vqshiftnu:
17528 case Intrinsic::arm_neon_vqshiftnsu:
17529 case Intrinsic::arm_neon_vqrshiftns:
17530 case Intrinsic::arm_neon_vqrshiftnu:
17531 case Intrinsic::arm_neon_vqrshiftnsu: {
17532 EVT VT =
N->getOperand(1).getValueType();
17534 unsigned VShiftOpc = 0;
17537 case Intrinsic::arm_neon_vshifts:
17538 case Intrinsic::arm_neon_vshiftu:
17543 if (
isVShiftRImm(
N->getOperand(2), VT,
false,
true, Cnt)) {
17550 case Intrinsic::arm_neon_vrshifts:
17551 case Intrinsic::arm_neon_vrshiftu:
17556 case Intrinsic::arm_neon_vqshifts:
17557 case Intrinsic::arm_neon_vqshiftu:
17562 case Intrinsic::arm_neon_vqshiftsu:
17567 case Intrinsic::arm_neon_vrshiftn:
17568 case Intrinsic::arm_neon_vqshiftns:
17569 case Intrinsic::arm_neon_vqshiftnu:
17570 case Intrinsic::arm_neon_vqshiftnsu:
17571 case Intrinsic::arm_neon_vqrshiftns:
17572 case Intrinsic::arm_neon_vqrshiftnu:
17573 case Intrinsic::arm_neon_vqrshiftnsu:
17585 case Intrinsic::arm_neon_vshifts:
17586 case Intrinsic::arm_neon_vshiftu:
17589 case Intrinsic::arm_neon_vrshifts:
17592 case Intrinsic::arm_neon_vrshiftu:
17595 case Intrinsic::arm_neon_vrshiftn:
17598 case Intrinsic::arm_neon_vqshifts:
17601 case Intrinsic::arm_neon_vqshiftu:
17604 case Intrinsic::arm_neon_vqshiftsu:
17607 case Intrinsic::arm_neon_vqshiftns:
17610 case Intrinsic::arm_neon_vqshiftnu:
17613 case Intrinsic::arm_neon_vqshiftnsu:
17616 case Intrinsic::arm_neon_vqrshiftns:
17619 case Intrinsic::arm_neon_vqrshiftnu:
17622 case Intrinsic::arm_neon_vqrshiftnsu:
17628 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17629 N->getOperand(1), DAG.
getConstant(Cnt, dl, MVT::i32));
17632 case Intrinsic::arm_neon_vshiftins: {
17633 EVT VT =
N->getOperand(1).getValueType();
17635 unsigned VShiftOpc = 0;
17639 else if (
isVShiftRImm(
N->getOperand(3), VT,
false,
true, Cnt))
17646 return DAG.
getNode(VShiftOpc, dl,
N->getValueType(0),
17647 N->getOperand(1),
N->getOperand(2),
17651 case Intrinsic::arm_neon_vqrshifts:
17652 case Intrinsic::arm_neon_vqrshiftu:
17656 case Intrinsic::arm_mve_vqdmlah:
17657 case Intrinsic::arm_mve_vqdmlash:
17658 case Intrinsic::arm_mve_vqrdmlah:
17659 case Intrinsic::arm_mve_vqrdmlash:
17660 case Intrinsic::arm_mve_vmla_n_predicated:
17661 case Intrinsic::arm_mve_vmlas_n_predicated:
17662 case Intrinsic::arm_mve_vqdmlah_predicated:
17663 case Intrinsic::arm_mve_vqdmlash_predicated:
17664 case Intrinsic::arm_mve_vqrdmlah_predicated:
17665 case Intrinsic::arm_mve_vqrdmlash_predicated: {
17670 unsigned BitWidth =
N->getValueType(0).getScalarSizeInBits();
17677 case Intrinsic::arm_mve_minv:
17678 case Intrinsic::arm_mve_maxv:
17679 case Intrinsic::arm_mve_minav:
17680 case Intrinsic::arm_mve_maxav:
17681 case Intrinsic::arm_mve_minv_predicated:
17682 case Intrinsic::arm_mve_maxv_predicated:
17683 case Intrinsic::arm_mve_minav_predicated:
17684 case Intrinsic::arm_mve_maxav_predicated: {
17687 unsigned BitWidth =
N->getOperand(2)->getValueType(0).getScalarSizeInBits();
17694 case Intrinsic::arm_mve_addv: {
17697 bool Unsigned =
N->getConstantOperandVal(2);
17702 case Intrinsic::arm_mve_addlv:
17703 case Intrinsic::arm_mve_addlv_predicated: {
17706 bool Unsigned =
N->getConstantOperandVal(2);
17707 unsigned Opc = IntNo == Intrinsic::arm_mve_addlv ?
17712 for (
unsigned i = 1, e =
N->getNumOperands(); i < e; i++)
17735 EVT VT =
N->getValueType(0);
17737 if (ST->isThumb1Only() &&
N->getOpcode() ==
ISD::SHL && VT == MVT::i32 &&
17738 N->getOperand(0)->getOpcode() ==
ISD::AND &&
17739 N->getOperand(0)->hasOneUse()) {
17747 ConstantSDNode *ShiftAmtNode = dyn_cast<ConstantSDNode>(
N->getOperand(1));
17756 if (AndMask == 255 || AndMask == 65535)
17760 if (MaskedBits > ShiftAmt) {
17775 if (ST->hasMVEIntegerOps())
17780 switch (
N->getOpcode()) {
17793 if (
isVShiftRImm(
N->getOperand(1), VT,
false,
false, Cnt)) {
17794 unsigned VShiftOpc =
17797 return DAG.
getNode(VShiftOpc, dl, VT,
N->getOperand(0),
17813 if (!LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed() ||
17816 EVT FromVT = LD->getValueType(0);
17817 EVT ToVT =
N->getValueType(0);
17824 unsigned NumElements = 0;
17825 if (ToEltVT == MVT::i32 && FromEltVT == MVT::i8)
17827 if (ToEltVT == MVT::f32 && FromEltVT == MVT::f16)
17829 if (NumElements == 0 ||
17839 SDValue BasePtr = LD->getBasePtr();
17840 Align Alignment = LD->getOriginalAlign();
17861 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
17862 Alignment, MMOFlags, AAInfo);
17868 if (FromEltVT == MVT::f16) {
17871 for (
unsigned i = 0; i < Loads.
size(); i++) {
17897 if ((ST->hasNEON() || ST->hasMVEIntegerOps()) &&
17901 EVT VT =
N->getValueType(0);
17905 if (VT == MVT::i32 &&
17906 (EltVT == MVT::i8 || EltVT == MVT::i16) &&
17908 isa<ConstantSDNode>(Lane)) {
17911 switch (
N->getOpcode()) {
17925 if (ST->hasMVEIntegerOps())
17934 if (ST->hasMVEFloatOps())
17945 if ((Subtarget->isThumb() || !Subtarget->hasV6Ops()) &&
17949 EVT VT =
Op.getValueType();
17952 if (VT != MVT::i32 ||
17954 !isa<ConstantSDNode>(
Op.getOperand(1)) ||
17965 APInt MaxC = Max.getConstantOperandAPInt(1);
17968 !(MinC + 1).isPowerOf2())
17986 EVT VT =
N->getValueType(0);
17989 if (VT == MVT::i32)
17992 if (!ST->hasMVEIntegerOps())
17998 if (VT != MVT::v4i32 && VT != MVT::v8i16)
18001 auto IsSignedSaturate = [&](
SDNode *Min,
SDNode *Max) {
18009 if (VT == MVT::v4i32)
18010 SaturateC =
APInt(32, (1 << 15) - 1,
true);
18012 SaturateC =
APInt(16, (1 << 7) - 1,
true);
18019 MaxC != ~SaturateC)
18024 if (IsSignedSaturate(
N, N0.
getNode())) {
18027 if (VT == MVT::v4i32) {
18028 HalfVT = MVT::v8i16;
18029 ExtVT = MVT::v4i16;
18031 HalfVT = MVT::v16i8;
18046 auto IsUnsignedSaturate = [&](
SDNode *Min) {
18052 if (VT == MVT::v4i32)
18053 SaturateC =
APInt(32, (1 << 16) - 1,
true);
18055 SaturateC =
APInt(16, (1 << 8) - 1,
true);
18064 if (IsUnsignedSaturate(
N)) {
18068 if (VT == MVT::v4i32) {
18069 HalfVT = MVT::v8i16;
18070 ExtConst = 0x0000FFFF;
18072 HalfVT = MVT::v16i8;
18094 const APInt *CV = &
C->getAPIntValue();
18112 SDValue Op0 = CMOV->getOperand(0);
18113 SDValue Op1 = CMOV->getOperand(1);
18114 auto CC = CMOV->getConstantOperandAPInt(2).getLimitedValue();
18115 SDValue CmpZ = CMOV->getOperand(4);
18151 unsigned Heuristic = Subtarget->isThumb() ? 3 : 2;
18158 if ((OrCI & Known.
Zero) != OrCI)
18164 EVT VT =
X.getValueType();
18165 unsigned BitInX = AndC->
logBase2();
18173 for (
unsigned BitInY = 0, NumActiveBits = OrCI.
getActiveBits();
18174 BitInY < NumActiveBits; ++BitInY) {
18175 if (OrCI[BitInY] == 0)
18178 Mask.setBit(BitInY);
18195 switch (
N->getOpcode()) {
18199 if (!isa<ConstantSDNode>(
N.getOperand(1)))
18201 if (!cast<ConstantSDNode>(
N.getOperand(1))->isOne())
18207 auto *Const = dyn_cast<ConstantSDNode>(
N.getOperand(1));
18210 if (Const->isZero())
18212 else if (Const->isOne())
18216 CC = cast<CondCodeSDNode>(
N.getOperand(2))->get();
18220 unsigned IntOp =
N.getConstantOperandVal(1);
18221 if (IntOp != Intrinsic::test_start_loop_iterations &&
18222 IntOp != Intrinsic::loop_decrement_reg)
18248 bool Negate =
false;
18254 Cond =
N->getOperand(1);
18255 Dest =
N->getOperand(2);
18258 CC = cast<CondCodeSDNode>(
N->getOperand(1))->get();
18259 Cond =
N->getOperand(2);
18260 Dest =
N->getOperand(4);
18261 if (
auto *Const = dyn_cast<ConstantSDNode>(
N->getOperand(3))) {
18262 if (!Const->isOne() && !Const->isZero())
18264 Imm = Const->getZExtValue();
18292 assert((IsTrueIfZero(
CC, Imm) || IsFalseIfZero(
CC, Imm)) &&
18293 "unsupported condition");
18298 unsigned IntOp =
Int->getConstantOperandVal(1);
18300 &&
"expected single br user");
18301 SDNode *Br = *
N->use_begin();
18311 if (IntOp == Intrinsic::test_start_loop_iterations) {
18315 if (IsTrueIfZero(
CC, Imm)) {
18316 SDValue Ops[] = {Chain, Setup, Dest};
18321 UpdateUncondBr(Br, Dest, DAG);
18323 SDValue Ops[] = {Chain, Setup, OtherTarget};
18336 DAG.
getVTList(MVT::i32, MVT::Other), Args);
18344 if (
Target == OtherTarget)
18345 UpdateUncondBr(Br, Dest, DAG);
18364 EVT VT =
N->getValueType(0);
18383 LHS->getOperand(0)->getOperand(3),
LHS->getOperand(0)->getOperand(4));
18397 EVT VT =
N->getValueType(0);
18401 SDValue FalseVal =
N->getOperand(0);
18402 SDValue TrueVal =
N->getOperand(1);
18407 if (!Subtarget->
isThumb1Only() && Subtarget->hasV6T2Ops()) {
18433 N->getOperand(3), Cmp);
18438 N->getOperand(3), NewCmp);
18447 LHS->getOperand(2),
LHS->getOperand(3),
18448 LHS->getOperand(4));
18458 if (
N->getConstantOperandVal(2) ==
ARMCC::EQ ||
18462 if (
N->getConstantOperandVal(2) ==
ARMCC::NE)
18464 return DAG.
getNode(
N->getOpcode(),
SDLoc(
N), MVT::i32,
N->getOperand(0),
18467 N->getOperand(3),
C);
18474 if (!Subtarget->
isThumb1Only() && Subtarget->hasV5TOps()) {
18510 N->getOperand(3), CPSRGlue.
getValue(1));
18525 N->getOperand(3), CPSRGlue.
getValue(1));
18543 const APInt *TrueConst;
18545 ((FalseVal.getOpcode() ==
ARMISD::SUBC && FalseVal.getOperand(0) ==
LHS &&
18546 FalseVal.getOperand(1) ==
RHS) ||
18550 unsigned ShiftAmount = TrueConst->
logBase2();
18565 if (Known.
Zero == 0xfffffffe)
18568 else if (Known.
Zero == 0xffffff00)
18571 else if (Known.
Zero == 0xffff0000)
18584 EVT DstVT =
N->getValueType(0);
18587 if (ST->hasMVEIntegerOps() && Src.getOpcode() ==
ARMISD::VDUP) {
18588 EVT SrcVT = Src.getValueType();
18596 Src = Src.getOperand(0);
18600 EVT SrcVT = Src.getValueType();
18620 EVT VT =
N->getValueType(0);
18628 if (
N->getNumOperands() == 2 &&
18632 N->getOperand(0).getOperand(1),
18633 N->getOperand(1).getOperand(0),
18634 N->getOperand(1).getOperand(1));
18637 if (
N->getNumOperands() == 2 &&
18640 auto *S0 = cast<ShuffleVectorSDNode>(
N->getOperand(0).getNode());
18641 auto *
S1 = cast<ShuffleVectorSDNode>(
N->getOperand(1).getNode());
18643 if (S0->getOperand(0) ==
S1->getOperand(0) &&
18644 S0->getOperand(1) ==
S1->getOperand(1)) {
18647 Mask.append(
S1->getMask().begin(),
S1->getMask().end());
18667 return Op.getOpcode() == ISD::BUILD_VECTOR ||
18668 Op.getOpcode() == ISD::VECTOR_SHUFFLE ||
18669 (Op.getOpcode() == ISD::BITCAST &&
18670 Op.getOperand(0).getOpcode() == ISD::BUILD_VECTOR);
18673 for (
unsigned Op = 0;
Op <
N->getNumOperands();
Op++) {
18675 for (
unsigned i = 0; i < O.getValueType().getVectorNumElements(); i++) {
18692 int SPFI = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
18693 int NumIns =
N->getNumOperands();
18694 assert((NumIns == 2 || NumIns == 4) &&
18695 "Expected 2 or 4 inputs to an MVETrunc");
18697 if (
N->getNumOperands() == 4)
18701 for (
int I = 0;
I < NumIns;
I++) {
18703 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18723 if (!LD || !LD->isSimple() || !N0.
hasOneUse() || LD->isIndexed())
18726 EVT FromVT = LD->getMemoryVT();
18727 EVT ToVT =
N->getValueType(0);
18734 unsigned NumElements = 0;
18735 if (ToEltVT == MVT::i32 && (FromEltVT == MVT::i16 || FromEltVT == MVT::i8))
18737 if (ToEltVT == MVT::i16 && FromEltVT == MVT::i8)
18739 assert(NumElements != 0);
18745 LD->getExtensionType() != NewExtType)
18752 SDValue BasePtr = LD->getBasePtr();
18753 Align Alignment = LD->getOriginalAlign();
18772 LD->getPointerInfo().getWithOffset(NewOffset), NewFromVT,
18773 Alignment, MMOFlags, AAInfo);
18789 EVT VT =
N->getValueType(0);
18791 assert(
N->getNumValues() == 2 &&
"Expected MVEEXT with 2 elements");
18792 assert((VT == MVT::v4i32 || VT == MVT::v8i16) &&
"Unexpected MVEEXT type");
18794 EVT ExtVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18796 auto Extend = [&](
SDValue V) {
18806 SDValue Ext = Extend(
N->getOperand(0));
18811 if (
auto *SVN = dyn_cast<ShuffleVectorSDNode>(
N->getOperand(0))) {
18814 assert(Mask.size() == SVN->getValueType(0).getVectorNumElements());
18819 auto CheckInregMask = [&](
int Start,
int Offset) {
18827 if (CheckInregMask(0, 0))
18829 else if (CheckInregMask(0, 1))
18830 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18831 else if (CheckInregMask(0, Mask.size()))
18833 else if (CheckInregMask(0, Mask.size() + 1))
18834 V0 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18839 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op1));
18843 V1 = Extend(DAG.
getNode(Rev,
DL, SVN->getValueType(0), Op0));
18850 if (
N->getOperand(0)->getOpcode() ==
ISD::LOAD)
18860 int SPFI = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
18861 int NumOuts =
N->getNumValues();
18862 assert((NumOuts == 2 || NumOuts == 4) &&
18863 "Expected 2 or 4 outputs to an MVEEXT");
18864 EVT LoadVT =
N->getOperand(0).getValueType().getHalfNumVectorElementsVT(
18866 if (
N->getNumOperands() == 4)
18872 StackPtr, MPI,
Align(4));
18875 for (
int I = 0;
I < NumOuts;
I++) {
18877 ISD::ADD,
DL, StackPtr.getValueType(), StackPtr,
18878 DAG.
getConstant(
I * 16 / NumOuts,
DL, StackPtr.getValueType()));
18883 VT, Chain,
Ptr, MPI, LoadVT,
Align(4));
18892 switch (
N->getOpcode()) {
19009 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19016 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19027 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19035 unsigned LowWidth =
N->getOperand(0).getValueType().getSizeInBits();
19037 unsigned HighWidth =
N->getOperand(1).getValueType().getSizeInBits();
19045 unsigned HighWidth =
N->getOperand(0).getValueType().getSizeInBits();
19047 unsigned LowWidth =
N->getOperand(1).getValueType().getSizeInBits();
19055 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19066 unsigned BitWidth =
N->getValueType(0).getSizeInBits();
19075 switch (
N->getConstantOperandVal(1)) {
19076 case Intrinsic::arm_neon_vld1:
19077 case Intrinsic::arm_neon_vld1x2:
19078 case Intrinsic::arm_neon_vld1x3:
19079 case Intrinsic::arm_neon_vld1x4:
19080 case Intrinsic::arm_neon_vld2:
19081 case Intrinsic::arm_neon_vld3:
19082 case Intrinsic::arm_neon_vld4:
19083 case Intrinsic::arm_neon_vld2lane:
19084 case Intrinsic::arm_neon_vld3lane:
19085 case Intrinsic::arm_neon_vld4lane:
19086 case Intrinsic::arm_neon_vld2dup:
19087 case Intrinsic::arm_neon_vld3dup:
19088 case Intrinsic::arm_neon_vld4dup:
19089 case Intrinsic::arm_neon_vst1:
19090 case Intrinsic::arm_neon_vst1x2:
19091 case Intrinsic::arm_neon_vst1x3:
19092 case Intrinsic::arm_neon_vst1x4:
19093 case Intrinsic::arm_neon_vst2:
19094 case Intrinsic::arm_neon_vst3:
19095 case Intrinsic::arm_neon_vst4:
19096 case Intrinsic::arm_neon_vst2lane:
19097 case Intrinsic::arm_neon_vst3lane:
19098 case Intrinsic::arm_neon_vst4lane:
19100 case Intrinsic::arm_mve_vld2q:
19101 case Intrinsic::arm_mve_vld4q:
19102 case Intrinsic::arm_mve_vst2q:
19103 case Intrinsic::arm_mve_vst4q:
19120 unsigned *
Fast)
const {
19129 if (Ty == MVT::i8 || Ty == MVT::i16 || Ty == MVT::i32) {
19131 if (AllowsUnaligned) {
19133 *
Fast = Subtarget->hasV7Ops();
19138 if (Ty == MVT::f64 || Ty == MVT::v2f64) {
19142 if (Subtarget->hasNEON() && (AllowsUnaligned || Subtarget->
isLittle())) {
19149 if (!Subtarget->hasMVEIntegerOps())
19153 if ((Ty == MVT::v16i1 || Ty == MVT::v8i1 || Ty == MVT::v4i1 ||
19154 Ty == MVT::v2i1)) {
19162 if ((Ty == MVT::v4i8 || Ty == MVT::v8i8 || Ty == MVT::v4i16) &&
19178 if (Ty == MVT::v16i8 || Ty == MVT::v8i16 || Ty == MVT::v8f16 ||
19179 Ty == MVT::v4i32 || Ty == MVT::v4f32 || Ty == MVT::v2i64 ||
19180 Ty == MVT::v2f64) {
19193 if ((
Op.isMemcpy() ||
Op.isZeroMemset()) && Subtarget->hasNEON() &&
19194 !FuncAttributes.
hasFnAttr(Attribute::NoImplicitFloat)) {
19196 if (
Op.size() >= 16 &&
19202 }
else if (
Op.size() >= 8 &&
19223 return (SrcBits == 64 && DestBits == 32);
19232 return (SrcBits == 64 && DestBits == 32);
19268 return Subtarget->hasFullFP16();
19278 return Ext->getType()->getScalarSizeInBits() ==
19279 2 * Ext->getOperand(0)->getType()->getScalarSizeInBits();
19284 !areExtDoubled(cast<Instruction>(Ext1)) ||
19285 !areExtDoubled(cast<Instruction>(Ext2)))
19296 if (!
I->getType()->isVectorTy())
19299 if (Subtarget->hasNEON()) {
19300 switch (
I->getOpcode()) {
19301 case Instruction::Sub:
19302 case Instruction::Add: {
19314 if (!Subtarget->hasMVEIntegerOps())
19318 if (!
I->hasOneUse())
19320 auto *Sub = cast<Instruction>(*
I->users().begin());
19321 return Sub->getOpcode() == Instruction::FSub && Sub->getOperand(1) ==
I;
19331 switch (
I->getOpcode()) {
19332 case Instruction::Add:
19333 case Instruction::Mul:
19334 case Instruction::FAdd:
19335 case Instruction::ICmp:
19336 case Instruction::FCmp:
19338 case Instruction::FMul:
19339 return !IsFMSMul(
I);
19340 case Instruction::Sub:
19341 case Instruction::FSub:
19342 case Instruction::Shl:
19343 case Instruction::LShr:
19344 case Instruction::AShr:
19345 return Operand == 1;
19346 case Instruction::Call:
19347 if (
auto *
II = dyn_cast<IntrinsicInst>(
I)) {
19348 switch (
II->getIntrinsicID()) {
19349 case Intrinsic::fma:
19351 case Intrinsic::sadd_sat:
19352 case Intrinsic::uadd_sat:
19353 case Intrinsic::arm_mve_add_predicated:
19354 case Intrinsic::arm_mve_mul_predicated:
19355 case Intrinsic::arm_mve_qadd_predicated:
19356 case Intrinsic::arm_mve_vhadd:
19357 case Intrinsic::arm_mve_hadd_predicated:
19358 case Intrinsic::arm_mve_vqdmull:
19359 case Intrinsic::arm_mve_vqdmull_predicated:
19360 case Intrinsic::arm_mve_vqdmulh:
19361 case Intrinsic::arm_mve_qdmulh_predicated:
19362 case Intrinsic::arm_mve_vqrdmulh:
19363 case Intrinsic::arm_mve_qrdmulh_predicated:
19364 case Intrinsic::arm_mve_fma_predicated:
19366 case Intrinsic::ssub_sat:
19367 case Intrinsic::usub_sat:
19368 case Intrinsic::arm_mve_sub_predicated:
19369 case Intrinsic::arm_mve_qsub_predicated:
19370 case Intrinsic::arm_mve_hsub_predicated:
19371 case Intrinsic::arm_mve_vhsub:
19372 return Operand == 1;
19383 for (
auto OpIdx :
enumerate(
I->operands())) {
19384 Instruction *
Op = dyn_cast<Instruction>(OpIdx.value().get());
19386 if (!
Op ||
any_of(Ops, [&](
Use *U) {
return U->get() ==
Op; }))
19390 if (Shuffle->
getOpcode() == Instruction::BitCast)
19391 Shuffle = dyn_cast<Instruction>(Shuffle->
getOperand(0));
19398 if (!IsSinker(
I, OpIdx.index()))
19403 for (
Use &U :
Op->uses()) {
19405 if (!IsSinker(
Insn, U.getOperandNo()))
19418 if (!Subtarget->hasMVEIntegerOps())
19436 if (
auto *Ld = dyn_cast<MaskedLoadSDNode>(ExtVal.
getOperand(0))) {
19437 if (Ld->isExpandingLoad())
19441 if (Subtarget->hasMVEIntegerOps())
19486bool ARMTargetLowering::isFMAFasterThanFMulAndFAdd(
const MachineFunction &MF,
19494 return Subtarget->hasMVEFloatOps();
19512 unsigned Scale = 1;
19529 if ((V & (Scale - 1)) != 0)
19531 return isUInt<5>(V / Scale);
19538 if (VT.
isVector() && Subtarget->hasNEON())
19541 !Subtarget->hasMVEFloatOps())
19544 bool IsNeg =
false;
19550 unsigned NumBytes = std::max((
unsigned)VT.
getSizeInBits() / 8, 1U);
19553 if (VT.
isVector() && Subtarget->hasMVEIntegerOps()) {
19557 return isShiftedUInt<7,2>(V);
19560 return isShiftedUInt<7,1>(V);
19562 return isUInt<7>(V);
19569 if (VT.
isFloatingPoint() && NumBytes == 2 && Subtarget->hasFPRegs16())
19570 return isShiftedUInt<8, 1>(V);
19573 return isShiftedUInt<8, 2>(V);
19575 if (NumBytes == 1 || NumBytes == 2 || NumBytes == 4) {
19578 return isUInt<8>(V);
19579 return isUInt<12>(V);
19605 default:
return false;
19610 return isUInt<12>(V);
19613 return isUInt<8>(V);
19618 return isShiftedUInt<8, 2>(V);
19624 int Scale = AM.
Scale;
19629 default:
return false;
19637 Scale = Scale & ~1;
19638 return Scale == 2 || Scale == 4 || Scale == 8;
19655 if (Scale & 1)
return false;
19662 const int Scale = AM.
Scale;
19672 return (Scale == 1) || (!AM.
HasBaseReg && Scale == 2);
19688 switch (AM.
Scale) {
19705 int Scale = AM.
Scale;
19707 default:
return false;
19711 if (Scale < 0) Scale = -Scale;
19719 if (Scale == 1 || (AM.
HasBaseReg && Scale == -1))
19732 if (Scale & 1)
return false;
19745 if (!Subtarget->isThumb())
19752 return Imm >= 0 && Imm <= 255;
19761 int64_t AbsImm = std::abs(Imm);
19762 if (!Subtarget->isThumb())
19767 return AbsImm >= 0 && AbsImm <= 255;
19802 if (VT == MVT::i16 || ((VT == MVT::i8 || VT == MVT::i1) && isSEXTLoad)) {
19806 int RHSC = (int)
RHS->getZExtValue();
19807 if (RHSC < 0 && RHSC > -256) {
19817 }
else if (VT == MVT::i32 || VT == MVT::i8 || VT == MVT::i1) {
19820 int RHSC = (int)
RHS->getZExtValue();
19821 if (RHSC < 0 && RHSC > -0x1000) {
19863 int RHSC = (int)
RHS->getZExtValue();
19864 if (RHSC < 0 && RHSC > -0x100) {
19869 }
else if (RHSC > 0 && RHSC < 0x100) {
19880 bool isSEXTLoad,
bool IsMasked,
bool isLE,
19885 if (!isa<ConstantSDNode>(
Ptr->getOperand(1)))
19891 bool CanChangeType = isLE && !IsMasked;
19894 int RHSC = (int)
RHS->getZExtValue();
19896 auto IsInRange = [&](
int RHSC,
int Limit,
int Scale) {
19897 if (RHSC < 0 && RHSC > -Limit * Scale && RHSC % Scale == 0) {
19902 }
else if (RHSC > 0 && RHSC < Limit * Scale && RHSC % Scale == 0) {
19913 if (VT == MVT::v4i16) {
19914 if (Alignment >= 2 && IsInRange(RHSC, 0x80, 2))
19916 }
else if (VT == MVT::v4i8 || VT == MVT::v8i8) {
19917 if (IsInRange(RHSC, 0x80, 1))
19919 }
else if (Alignment >= 4 &&
19920 (CanChangeType || VT == MVT::v4i32 || VT == MVT::v4f32) &&
19921 IsInRange(RHSC, 0x80, 4))
19923 else if (Alignment >= 2 &&
19924 (CanChangeType || VT == MVT::v8i16 || VT == MVT::v8f16) &&
19925 IsInRange(RHSC, 0x80, 2))
19927 else if ((CanChangeType || VT == MVT::v16i8) && IsInRange(RHSC, 0x80, 1))
19946 bool isSEXTLoad =
false;
19947 bool IsMasked =
false;
19949 Ptr = LD->getBasePtr();
19950 VT = LD->getMemoryVT();
19951 Alignment = LD->getAlign();
19953 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
19954 Ptr = ST->getBasePtr();
19955 VT = ST->getMemoryVT();
19956 Alignment = ST->getAlign();
19958 Ptr = LD->getBasePtr();
19959 VT = LD->getMemoryVT();
19960 Alignment = LD->getAlign();
19964 Ptr = ST->getBasePtr();
19965 VT = ST->getMemoryVT();
19966 Alignment = ST->getAlign();
19972 bool isLegal =
false;
19974 isLegal = Subtarget->hasMVEIntegerOps() &&
19976 Ptr.getNode(), VT, Alignment, isSEXTLoad, IsMasked,
20004 bool isSEXTLoad =
false, isNonExt;
20005 bool IsMasked =
false;
20007 VT = LD->getMemoryVT();
20008 Ptr = LD->getBasePtr();
20009 Alignment = LD->getAlign();
20012 }
else if (
StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
20013 VT = ST->getMemoryVT();
20014 Ptr = ST->getBasePtr();
20015 Alignment = ST->getAlign();
20016 isNonExt = !ST->isTruncatingStore();
20018 VT = LD->getMemoryVT();
20019 Ptr = LD->getBasePtr();
20020 Alignment = LD->getAlign();
20025 VT = ST->getMemoryVT();
20026 Ptr = ST->getBasePtr();
20027 Alignment = ST->getAlign();
20028 isNonExt = !ST->isTruncatingStore();
20036 assert(
Op->getValueType(0) == MVT::i32 &&
"Non-i32 post-inc op?!");
20037 if (
Op->getOpcode() !=
ISD::ADD || !isNonExt)
20039 auto *
RHS = dyn_cast<ConstantSDNode>(
Op->getOperand(1));
20040 if (!
RHS ||
RHS->getZExtValue() != 4)
20042 if (Alignment <
Align(4))
20046 Base =
Op->getOperand(0);
20052 bool isLegal =
false;
20054 isLegal = Subtarget->hasMVEIntegerOps() &&
20087 const APInt &DemandedElts,
20089 unsigned Depth)
const {
20092 switch (
Op.getOpcode()) {
20099 if (
Op.getResNo() == 0) {
20125 case Intrinsic::arm_ldaex:
20126 case Intrinsic::arm_ldrex: {
20127 EVT VT = cast<MemIntrinsicSDNode>(
Op)->getMemoryVT();
20141 const APInt &Mask =
Op.getConstantOperandAPInt(2);
20142 Known.
Zero &= Mask;
20148 const SDValue &SrcSV =
Op.getOperand(0);
20154 "VGETLANE index out of bounds");
20159 EVT VT =
Op.getValueType();
20166 Known = Known.
sext(DstSz);
20168 Known = Known.
zext(DstSz);
20176 Known = KnownOp.
zext(32);
20216 EVT VT =
Op.getValueType();
20222 assert(VT == MVT::i32 &&
"Unexpected integer type");
20229 unsigned Mask =
C->getZExtValue();
20232 unsigned ShrunkMask = Mask & Demanded;
20233 unsigned ExpandedMask = Mask | ~Demanded;
20237 if (ShrunkMask == 0)
20243 if (ExpandedMask == ~0U)
20246 auto IsLegalMask = [ShrunkMask, ExpandedMask](
unsigned Mask) ->
bool {
20247 return (ShrunkMask & Mask) == ShrunkMask && (~ExpandedMask & Mask) == 0;
20249 auto UseMask = [Mask,
Op, VT, &TLO](
unsigned NewMask) ->
bool {
20250 if (NewMask == Mask)
20259 if (IsLegalMask(0xFF))
20260 return UseMask(0xFF);
20263 if (IsLegalMask(0xFFFF))
20264 return UseMask(0xFFFF);
20268 if (ShrunkMask < 256)
20269 return UseMask(ShrunkMask);
20273 if ((
int)ExpandedMask <= -2 && (
int)ExpandedMask >= -256)
20274 return UseMask(ExpandedMask);
20289 unsigned Depth)
const {
20290 unsigned Opc =
Op.getOpcode();
20298 if (
Op.getResNo() == 0 && !
Op->hasAnyUseOfValue(1) &&
20299 isa<ConstantSDNode>(
Op->getOperand(2))) {
20300 unsigned ShAmt =
Op->getConstantOperandVal(2);
20312 unsigned ModImm =
Op.getConstantOperandVal(1);
20313 unsigned EltBits = 0;
20315 if ((OriginalDemandedBits & Mask) == 0)
20321 Op, OriginalDemandedBits, OriginalDemandedElts, Known, TLO,
Depth);
20330 if (!Subtarget->hasV6Ops())
20336 SplitString(AsmStr, AsmPieces,
";\n");
20338 switch (AsmPieces.
size()) {
20339 default:
return false;
20341 AsmStr = AsmPieces[0];
20343 SplitString(AsmStr, AsmPieces,
" \t,");
20346 if (AsmPieces.
size() == 3 &&
20347 AsmPieces[0] ==
"rev" && AsmPieces[1] ==
"$0" && AsmPieces[2] ==
"$1" &&
20348 IA->getConstraintString().compare(0, 4,
"=l,l") == 0) {
20371 if (ConstraintVT.
isVector() && Subtarget->hasNEON() &&
20383 unsigned S = Constraint.
size();
20385 switch (Constraint[0]) {
20397 }
else if (S == 2) {
20398 switch (Constraint[0]) {
20415 Value *CallOperandVal =
info.CallOperandVal;
20418 if (!CallOperandVal)
20422 switch (*constraint) {
20428 if (Subtarget->isThumb())
20442using RCPair = std::pair<unsigned, const TargetRegisterClass *>;
20446 switch (Constraint.
size()) {
20449 switch (Constraint[0]) {
20451 if (Subtarget->isThumb())
20452 return RCPair(0U, &ARM::tGPRRegClass);
20453 return RCPair(0U, &ARM::GPRRegClass);
20455 if (Subtarget->isThumb())
20456 return RCPair(0U, &ARM::hGPRRegClass);
20460 return RCPair(0U, &ARM::tGPRRegClass);
20461 return RCPair(0U, &ARM::GPRRegClass);
20463 if (VT == MVT::Other)
20465 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20466 return RCPair(0U, &ARM::SPRRegClass);
20468 return RCPair(0U, &ARM::DPRRegClass);
20470 return RCPair(0U, &ARM::QPRRegClass);
20473 if (VT == MVT::Other)
20475 if (VT == MVT::f32 || VT == MVT::f16 || VT == MVT::bf16)
20476 return RCPair(0U, &ARM::SPR_8RegClass);
20478 return RCPair(0U, &ARM::DPR_8RegClass);
20480 return RCPair(0U, &ARM::QPR_8RegClass);
20483 if (VT == MVT::Other)
20485 if (VT == MVT::f32 || VT == MVT::i32 || VT == MVT::f16 || VT == MVT::bf16)
20486 return RCPair(0U, &ARM::SPRRegClass);
20488 return RCPair(0U, &ARM::DPR_VFP2RegClass);
20490 return RCPair(0U, &ARM::QPR_VFP2RegClass);
20496 if (Constraint[0] ==
'T') {
20497 switch (Constraint[1]) {
20501 return RCPair(0U, &ARM::tGPREvenRegClass);
20503 return RCPair(0U, &ARM::tGPROddRegClass);
20512 if (
StringRef(
"{cc}").equals_insensitive(Constraint))
20513 return std::make_pair(
unsigned(ARM::CPSR), &ARM::CCRRegClass);
20522 std::vector<SDValue> &Ops,
20527 if (Constraint.
size() != 1)
20530 char ConstraintLetter = Constraint[0];
20531 switch (ConstraintLetter) {
20534 case 'I':
case 'J':
case 'K':
case 'L':
20535 case 'M':
case 'N':
case 'O':
20540 int64_t CVal64 =
C->getSExtValue();
20541 int CVal = (int) CVal64;
20544 if (CVal != CVal64)
20547 switch (ConstraintLetter) {
20551 if (Subtarget->hasV6T2Ops() || (Subtarget->hasV8MBaselineOps()))
20552 if (CVal >= 0 && CVal <= 65535)
20559 if (CVal >= 0 && CVal <= 255)
20561 }
else if (Subtarget->
isThumb2()) {
20580 if (CVal >= -255 && CVal <= -1)
20586 if (CVal >= -4095 && CVal <= 4095)
20599 }
else if (Subtarget->
isThumb2()) {
20622 if (CVal >= -7 && CVal < 7)
20624 }
else if (Subtarget->
isThumb2()) {
20647 if ((CVal >= 0 && CVal <= 1020) && ((CVal & 3) == 0))
20653 if ((CVal >= 0 && CVal <= 32) || ((CVal & (CVal - 1)) == 0))
20661 if (CVal >= 0 && CVal <= 31)
20670 if ((CVal >= -508 && CVal <= 508) && ((CVal & 3) == 0))
20680 if (Result.getNode()) {
20681 Ops.push_back(Result);
20691 "Unhandled Opcode in getDivRemLibcall");
20697 case MVT::i8: LC =
isSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
break;
20698 case MVT::i16: LC =
isSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
break;
20699 case MVT::i32: LC =
isSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
break;
20700 case MVT::i64: LC =
isSigned ? RTLIB::SDIVREM_I64 : RTLIB::UDIVREM_I64;
break;
20709 "Unhandled Opcode in getDivRemArgList");
20714 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
20715 EVT ArgVT =
N->getOperand(i).getValueType();
20717 Entry.Node =
N->getOperand(i);
20721 Args.push_back(Entry);
20732 "Register-based DivRem lowering only");
20733 unsigned Opcode =
Op->getOpcode();
20735 "Invalid opcode for Div/Rem lowering");
20737 EVT VT =
Op->getValueType(0);
20740 if (VT == MVT::i64 && isa<ConstantSDNode>(
Op.getOperand(1))) {
20759 bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivideInThumbMode()
20760 : Subtarget->hasDivideInARMMode();
20761 if (hasDivide &&
Op->getValueType(0).isSimple() &&
20762 Op->getSimpleValueType(0) == MVT::i32) {
20764 const SDValue Dividend =
Op->getOperand(0);
20765 const SDValue Divisor =
Op->getOperand(1);
20766 SDValue Div = DAG.
getNode(DivOpcode, dl, VT, Dividend, Divisor);
20770 SDValue Values[2] = {Div, Rem};
20802 EVT VT =
N->getValueType(0);
20804 if (VT == MVT::i64 && isa<ConstantSDNode>(
N->getOperand(1))) {
20808 Result[0], Result[1]);
20812 std::vector<Type*> RetTyParams;
20813 Type *RetTyElement;
20823 RetTyParams.push_back(RetTyElement);
20824 RetTyParams.push_back(RetTyElement);
20841 CallLoweringInfo CLI(DAG);
20845 std::pair<SDValue, SDValue> CallResult =
LowerCallTo(CLI);
20848 SDNode *ResNode = CallResult.first.getNode();
20863 "no-stack-arg-probe")) {
20865 cast<ConstantSDNode>(
Op.getOperand(2))->getMaybeAlignValue();
20874 SDValue Ops[2] = { SP, Chain };
20891 SDValue Ops[2] = { NewSP, Chain };
20896 bool IsStrict =
Op->isStrictFPOpcode();
20897 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20898 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20900 assert(DstSz > SrcSz && DstSz <= 64 && SrcSz >= 16 &&
20901 "Unexpected type for custom-lowering FP_EXTEND");
20904 "With both FP DP and 16, any FP conversion is legal!");
20906 assert(!(DstSz == 32 && Subtarget->hasFP16()) &&
20907 "With FP16, 16 to 32 conversion is legal!");
20910 if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) {
20915 Loc,
Op.getValueType(), SrcVal);
20928 MakeLibCallOptions CallOptions;
20930 for (
unsigned Sz = SrcSz; Sz <= 32 && Sz < DstSz; Sz *= 2) {
20931 bool Supported = (Sz == 16 ? Subtarget->hasFP16() : Subtarget->hasFP64());
20932 MVT SrcVT = (Sz == 16 ? MVT::f16 : MVT::f32);
20933 MVT DstVT = (Sz == 16 ? MVT::f32 : MVT::f64);
20937 {DstVT, MVT::Other}, {Chain, SrcVal});
20944 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20945 "Unexpected type for custom-lowering FP_EXTEND");
20946 std::tie(SrcVal, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20951 return IsStrict ? DAG.
getMergeValues({SrcVal, Chain}, Loc) : SrcVal;
20955 bool IsStrict =
Op->isStrictFPOpcode();
20957 SDValue SrcVal =
Op.getOperand(IsStrict ? 1 : 0);
20959 EVT DstVT =
Op.getValueType();
20960 const unsigned DstSz =
Op.getValueType().getSizeInBits();
20963 assert(DstSz < SrcSz && SrcSz <= 64 && DstSz >= 16 &&
20964 "Unexpected type for custom-lowering FP_ROUND");
20967 "With both FP DP and 16, any FP conversion is legal!");
20972 if (SrcSz == 32 && Subtarget->hasFP16())
20977 assert(LC != RTLIB::UNKNOWN_LIBCALL &&
20978 "Unexpected type for custom-lowering FP_ROUND");
20979 MakeLibCallOptions CallOptions;
20982 std::tie(Result, Chain) =
makeLibCall(DAG, LC, DstVT, SrcVal, CallOptions,
20994 if (v == 0xffffffff)
21006 bool ForCodeSize)
const {
21009 if (VT == MVT::f16 && Subtarget->hasFullFP16())
21011 if (VT == MVT::f32 && Subtarget->hasFullFP16() &&
21014 if (VT == MVT::f32)
21016 if (VT == MVT::f64 && Subtarget->hasFP64())
21027 unsigned Intrinsic)
const {
21028 switch (Intrinsic) {
21029 case Intrinsic::arm_neon_vld1:
21030 case Intrinsic::arm_neon_vld2:
21031 case Intrinsic::arm_neon_vld3:
21032 case Intrinsic::arm_neon_vld4:
21033 case Intrinsic::arm_neon_vld2lane:
21034 case Intrinsic::arm_neon_vld3lane:
21035 case Intrinsic::arm_neon_vld4lane:
21036 case Intrinsic::arm_neon_vld2dup:
21037 case Intrinsic::arm_neon_vld3dup:
21038 case Intrinsic::arm_neon_vld4dup: {
21041 auto &
DL =
I.getDataLayout();
21042 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
21044 Info.ptrVal =
I.getArgOperand(0);
21046 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
21047 Info.align = cast<ConstantInt>(AlignArg)->getMaybeAlignValue();
21052 case Intrinsic::arm_neon_vld1x2:
21053 case Intrinsic::arm_neon_vld1x3:
21054 case Intrinsic::arm_neon_vld1x4: {
21057 auto &
DL =
I.getDataLayout();
21058 uint64_t NumElts =
DL.getTypeSizeInBits(
I.getType()) / 64;
21060 Info.ptrVal =
I.getArgOperand(
I.arg_size() - 1);
21062 Info.align.reset();
21067 case Intrinsic::arm_neon_vst1:
21068 case Intrinsic::arm_neon_vst2:
21069 case Intrinsic::arm_neon_vst3:
21070 case Intrinsic::arm_neon_vst4:
21071 case Intrinsic::arm_neon_vst2lane:
21072 case Intrinsic::arm_neon_vst3lane:
21073 case Intrinsic::arm_neon_vst4lane: {
21076 auto &
DL =
I.getDataLayout();
21077 unsigned NumElts = 0;
21078 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
21079 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
21082 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21085 Info.ptrVal =
I.getArgOperand(0);
21087 Value *AlignArg =
I.getArgOperand(
I.arg_size() - 1);
21088 Info.align = cast<ConstantInt>(AlignArg)->getMaybeAlignValue();
21093 case Intrinsic::arm_neon_vst1x2:
21094 case Intrinsic::arm_neon_vst1x3:
21095 case Intrinsic::arm_neon_vst1x4: {
21098 auto &
DL =
I.getDataLayout();
21099 unsigned NumElts = 0;
21100 for (
unsigned ArgI = 1, ArgE =
I.arg_size(); ArgI < ArgE; ++ArgI) {
21101 Type *ArgTy =
I.getArgOperand(ArgI)->getType();
21104 NumElts +=
DL.getTypeSizeInBits(ArgTy) / 64;
21107 Info.ptrVal =
I.getArgOperand(0);
21109 Info.align.reset();
21114 case Intrinsic::arm_mve_vld2q:
21115 case Intrinsic::arm_mve_vld4q: {
21118 Type *VecTy = cast<StructType>(
I.getType())->getElementType(1);
21119 unsigned Factor = Intrinsic == Intrinsic::arm_mve_vld2q ? 2 : 4;
21121 Info.ptrVal =
I.getArgOperand(0);
21128 case Intrinsic::arm_mve_vst2q:
21129 case Intrinsic::arm_mve_vst4q: {
21132 Type *VecTy =
I.getArgOperand(1)->getType();
21133 unsigned Factor = Intrinsic == Intrinsic::arm_mve_vst2q ? 2 : 4;
21135 Info.ptrVal =
I.getArgOperand(0);
21142 case Intrinsic::arm_mve_vldr_gather_base:
21143 case Intrinsic::arm_mve_vldr_gather_base_predicated: {
21145 Info.ptrVal =
nullptr;
21151 case Intrinsic::arm_mve_vldr_gather_base_wb:
21152 case Intrinsic::arm_mve_vldr_gather_base_wb_predicated: {
21154 Info.ptrVal =
nullptr;
21160 case Intrinsic::arm_mve_vldr_gather_offset:
21161 case Intrinsic::arm_mve_vldr_gather_offset_predicated: {
21163 Info.ptrVal =
nullptr;
21165 unsigned MemSize = cast<ConstantInt>(
I.getArgOperand(2))->getZExtValue();
21172 case Intrinsic::arm_mve_vstr_scatter_base:
21173 case Intrinsic::arm_mve_vstr_scatter_base_predicated: {
21175 Info.ptrVal =
nullptr;
21181 case Intrinsic::arm_mve_vstr_scatter_base_wb:
21182 case Intrinsic::arm_mve_vstr_scatter_base_wb_predicated: {
21184 Info.ptrVal =
nullptr;
21190 case Intrinsic::arm_mve_vstr_scatter_offset:
21191 case Intrinsic::arm_mve_vstr_scatter_offset_predicated: {
21193 Info.ptrVal =
nullptr;
21195 unsigned MemSize = cast<ConstantInt>(
I.getArgOperand(3))->getZExtValue();
21202 case Intrinsic::arm_ldaex:
21203 case Intrinsic::arm_ldrex: {
21204 auto &
DL =
I.getDataLayout();
21205 Type *ValTy =
I.getParamElementType(0);
21208 Info.ptrVal =
I.getArgOperand(0);
21210 Info.align =
DL.getABITypeAlign(ValTy);
21214 case Intrinsic::arm_stlex:
21215 case Intrinsic::arm_strex: {
21216 auto &
DL =
I.getDataLayout();
21217 Type *ValTy =
I.getParamElementType(1);
21220 Info.ptrVal =
I.getArgOperand(1);
21222 Info.align =
DL.getABITypeAlign(ValTy);
21226 case Intrinsic::arm_stlexd:
21227 case Intrinsic::arm_strexd:
21229 Info.memVT = MVT::i64;
21230 Info.ptrVal =
I.getArgOperand(2);
21236 case Intrinsic::arm_ldaexd:
21237 case Intrinsic::arm_ldrexd:
21239 Info.memVT = MVT::i64;
21240 Info.ptrVal =
I.getArgOperand(0);
21260 if (Bits == 0 || Bits > 32)
21266 unsigned Index)
const {
21278 if (!Subtarget->hasDataBarrier()) {
21282 if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
21319 if (Subtarget->preferISHSTBarriers())
21352 bool has64BitAtomicStore;
21354 has64BitAtomicStore =
false;
21355 else if (Subtarget->isThumb())
21356 has64BitAtomicStore = Subtarget->hasV7Ops();
21358 has64BitAtomicStore = Subtarget->hasV6Ops();
21360 unsigned Size = SI->getValueOperand()->getType()->getPrimitiveSizeInBits();
21374 bool has64BitAtomicLoad;
21376 has64BitAtomicLoad =
false;
21377 else if (Subtarget->isThumb())
21378 has64BitAtomicLoad = Subtarget->hasV7Ops();
21380 has64BitAtomicLoad = Subtarget->hasV6Ops();
21397 hasAtomicRMW = Subtarget->hasV8MBaselineOps();
21398 else if (Subtarget->isThumb())
21399 hasAtomicRMW = Subtarget->hasV7Ops();
21401 hasAtomicRMW = Subtarget->hasV6Ops();
21402 if (
Size <= (Subtarget->
isMClass() ? 32U : 64U) && hasAtomicRMW) {
21425 bool HasAtomicCmpXchg;
21427 HasAtomicCmpXchg = Subtarget->hasV8MBaselineOps();
21428 else if (Subtarget->isThumb())
21429 HasAtomicCmpXchg = Subtarget->hasV7Ops();
21431 HasAtomicCmpXchg = Subtarget->hasV6Ops();
21433 HasAtomicCmpXchg &&
Size <= (Subtarget->
isMClass() ? 32U : 64U))
21440 return InsertFencesForAtomic;
21453 M.getOrInsertGlobal(
"__security_cookie",
21461 F->addParamAttr(0, Attribute::AttrKind::InReg);
21467 return M.getGlobalVariable(
"__security_cookie");
21474 return M.getFunction(
"__security_check_cookie");
21479 unsigned &
Cost)
const {
21481 if (!Subtarget->hasNEON())
21493 if (!isa<ConstantInt>(
Idx))
21508 return Subtarget->hasV6T2Ops();
21512 return Subtarget->hasV6T2Ops();
21517 if (!Subtarget->hasV7Ops())
21523 if (!Mask || Mask->getValue().getBitWidth() > 32u)
21525 auto MaskVal =
unsigned(Mask->getValue().getZExtValue());
21550 IsAcquire ? Intrinsic::arm_ldaexd : Intrinsic::arm_ldrexd;
21562 Lo, Builder.
CreateShl(
Hi, ConstantInt::get(ValueTy, 32)),
"val64");
21565 Type *Tys[] = {
Addr->getType() };
21566 Intrinsic::ID Int = IsAcquire ? Intrinsic::arm_ldaex : Intrinsic::arm_ldrex;
21571 0,
Attribute::get(M->getContext(), Attribute::ElementType, ValueTy));
21577 if (!Subtarget->hasV7Ops())
21594 IsRelease ? Intrinsic::arm_stlexd : Intrinsic::arm_strexd;
21605 Intrinsic::ID Int = IsRelease ? Intrinsic::arm_stlex : Intrinsic::arm_strex;
21606 Type *Tys[] = {
Addr->getType() };
21628 return (
DL.getTypeSizeInBits(VecTy) + 127) / 128;
21635 unsigned VecSize =
DL.getTypeSizeInBits(VecTy);
21638 if (!Subtarget->hasNEON() && !Subtarget->hasMVEIntegerOps())
21646 if (Subtarget->hasMVEIntegerOps() && Factor == 3)
21654 if (ElSize != 8 && ElSize != 16 && ElSize != 32)
21657 if (Subtarget->hasMVEIntegerOps() && Alignment < ElSize / 8)
21662 if (Subtarget->hasNEON() && VecSize == 64)
21664 return VecSize % 128 == 0;
21668 if (Subtarget->hasNEON())
21670 if (Subtarget->hasMVEIntegerOps())
21690 "Invalid interleave factor");
21691 assert(!Shuffles.
empty() &&
"Empty shufflevector input");
21693 "Unmatched number of shufflevectors and indices");
21695 auto *VecTy = cast<FixedVectorType>(Shuffles[0]->
getType());
21696 Type *EltTy = VecTy->getElementType();
21719 if (NumLoads > 1) {
21723 VecTy->getNumElements() / NumLoads);
21728 auto createLoadIntrinsic = [&](
Value *BaseAddr) {
21729 if (Subtarget->hasNEON()) {
21731 Type *Tys[] = {VecTy, PtrTy};
21732 static const Intrinsic::ID LoadInts[3] = {Intrinsic::arm_neon_vld2,
21733 Intrinsic::arm_neon_vld3,
21734 Intrinsic::arm_neon_vld4};
21742 return Builder.
CreateCall(VldnFunc, Ops,
"vldN");
21744 assert((Factor == 2 || Factor == 4) &&
21745 "expected interleave factor of 2 or 4 for MVE");
21747 Factor == 2 ? Intrinsic::arm_mve_vld2q : Intrinsic::arm_mve_vld4q;
21749 Type *Tys[] = {VecTy, PtrTy};
21755 return Builder.
CreateCall(VldnFunc, Ops,
"vldN");
21764 for (
unsigned LoadCount = 0; LoadCount < NumLoads; ++LoadCount) {
21769 VecTy->getNumElements() * Factor);
21771 CallInst *VldN = createLoadIntrinsic(BaseAddr);
21775 for (
unsigned i = 0; i < Shuffles.
size(); i++) {
21777 unsigned Index = Indices[i];
21787 SubVecs[SV].push_back(SubVec);
21796 auto &SubVec = SubVecs[SVI];
21799 SVI->replaceAllUsesWith(WideVec);
21833 unsigned Factor)
const {
21835 "Invalid interleave factor");
21837 auto *VecTy = cast<FixedVectorType>(SVI->
getType());
21838 assert(VecTy->getNumElements() % Factor == 0 &&
"Invalid interleaved store");
21840 unsigned LaneLen = VecTy->getNumElements() / Factor;
21841 Type *EltTy = VecTy->getElementType();
21845 Align Alignment = SI->getAlign();
21862 Type *IntTy =
DL.getIntPtrType(EltTy);
21874 Value *BaseAddr = SI->getPointerOperand();
21876 if (NumStores > 1) {
21879 LaneLen /= NumStores;
21887 auto createStoreIntrinsic = [&](
Value *BaseAddr,
21889 if (Subtarget->hasNEON()) {
21890 static const Intrinsic::ID StoreInts[3] = {Intrinsic::arm_neon_vst2,
21891 Intrinsic::arm_neon_vst3,
21892 Intrinsic::arm_neon_vst4};
21893 Type *PtrTy = Builder.
getPtrTy(SI->getPointerAddressSpace());
21894 Type *Tys[] = {PtrTy, SubVecTy};
21897 SI->getModule(), StoreInts[Factor - 2], Tys);
21905 assert((Factor == 2 || Factor == 4) &&
21906 "expected interleave factor of 2 or 4 for MVE");
21908 Factor == 2 ? Intrinsic::arm_mve_vst2q : Intrinsic::arm_mve_vst4q;
21909 Type *PtrTy = Builder.
getPtrTy(SI->getPointerAddressSpace());
21910 Type *Tys[] = {PtrTy, SubVecTy};
21917 for (
unsigned F = 0;
F < Factor;
F++) {
21925 for (
unsigned StoreCount = 0; StoreCount < NumStores; ++StoreCount) {
21928 if (StoreCount > 0)
21930 BaseAddr, LaneLen * Factor);
21935 for (
unsigned i = 0; i < Factor; i++) {
21936 unsigned IdxI = StoreCount * LaneLen * Factor + i;
21937 if (Mask[IdxI] >= 0) {
21941 unsigned StartMask = 0;
21942 for (
unsigned j = 1; j < LaneLen; j++) {
21943 unsigned IdxJ = StoreCount * LaneLen * Factor + j;
21944 if (Mask[IdxJ * Factor + IdxI] >= 0) {
21945 StartMask = Mask[IdxJ * Factor + IdxI] - IdxJ;
21960 createStoreIntrinsic(BaseAddr, Shuffles);
21975 if (
auto *ST = dyn_cast<StructType>(Ty)) {
21976 for (
unsigned i = 0; i < ST->getNumElements(); ++i) {
21980 Members += SubMembers;
21982 }
else if (
auto *AT = dyn_cast<ArrayType>(Ty)) {
21986 Members += SubMembers * AT->getNumElements();
21997 }
else if (
auto *VT = dyn_cast<VectorType>(Ty)) {
22004 return VT->getPrimitiveSizeInBits().getFixedValue() == 64;
22006 return VT->getPrimitiveSizeInBits().getFixedValue() == 128;
22008 switch (VT->getPrimitiveSizeInBits().getFixedValue()) {
22021 return (Members > 0 && Members <= 4);
22027 const Align ABITypeAlign =
DL.getABITypeAlign(ArgTy);
22029 return ABITypeAlign;
22033 return std::min(ABITypeAlign,
DL.getStackAlignment());
22042 if (getEffectiveCallingConv(CallConv, isVarArg) !=
22052 return IsHA || IsIntArray;
22056 const Constant *PersonalityFn)
const {
22063 const Constant *PersonalityFn)
const {
22075void ARMTargetLowering::insertCopiesSplitCSR(
22079 const MCPhysReg *IStart =
TRI->getCalleeSavedRegsViaCopy(Entry->getParent());
22089 RC = &ARM::GPRRegClass;
22090 else if (ARM::DPRRegClass.
contains(*
I))
22091 RC = &ARM::DPRRegClass;
22101 assert(Entry->getParent()->getFunction().hasFnAttribute(
22102 Attribute::NoUnwind) &&
22103 "Function should be nounwind in insertCopiesSplitCSR!");
22104 Entry->addLiveIn(*
I);
22109 for (
auto *Exit : Exits)
22111 TII->get(TargetOpcode::COPY), *
I)
22122 return Subtarget->hasMVEIntegerOps();
22127 auto *VTy = dyn_cast<FixedVectorType>(Ty);
22132 unsigned NumElements = VTy->getNumElements();
22139 if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy())
22140 return Subtarget->hasMVEFloatOps();
22145 return Subtarget->hasMVEIntegerOps() &&
22146 (ScalarTy->isIntegerTy(8) || ScalarTy->isIntegerTy(16) ||
22147 ScalarTy->isIntegerTy(32));
22159 assert(TyWidth >= 128 &&
"Width of vector type must be at least 128 bits");
22161 if (TyWidth > 128) {
22166 ArrayRef<int> UpperSplitMask(&SplitSeqVec[Stride], Stride);
22168 auto *LowerSplitA =
B.CreateShuffleVector(InputA, LowerSplitMask);
22169 auto *LowerSplitB =
B.CreateShuffleVector(InputB, LowerSplitMask);
22170 auto *UpperSplitA =
B.CreateShuffleVector(InputA, UpperSplitMask);
22171 auto *UpperSplitB =
B.CreateShuffleVector(InputB, UpperSplitMask);
22172 Value *LowerSplitAcc =
nullptr;
22173 Value *UpperSplitAcc =
nullptr;
22176 LowerSplitAcc =
B.CreateShuffleVector(
Accumulator, LowerSplitMask);
22177 UpperSplitAcc =
B.CreateShuffleVector(
Accumulator, UpperSplitMask);
22181 B, OperationType, Rotation, LowerSplitA, LowerSplitB, LowerSplitAcc);
22183 B, OperationType, Rotation, UpperSplitA, UpperSplitB, UpperSplitAcc);
22186 return B.CreateShuffleVector(LowerSplitInt, UpperSplitInt, JoinMask);
22193 ConstRotation = ConstantInt::get(IntTy, (
int)Rotation);
22196 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmlaq, Ty,
22198 return B.CreateIntrinsic(Intrinsic::arm_mve_vcmulq, Ty,
22199 {ConstRotation, InputB, InputA});
22204 auto *ConstHalving = ConstantInt::get(IntTy, 1);
22207 ConstRotation = ConstantInt::get(IntTy, 0);
22209 ConstRotation = ConstantInt::get(IntTy, 1);
22211 if (!ConstRotation)
22214 return B.CreateIntrinsic(Intrinsic::arm_mve_vcaddq, Ty,
22215 {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 bool areExtractExts(Value *Ext1, Value *Ext2)
Check if Ext1 and Ext2 are extends of the same type, doubling the bitwidth of the vector elements.
static EVT getExtensionTo64Bits(const EVT &OrigVT)
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 SDValue createGPRPairNode(SelectionDAG &DAG, SDValue V)
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.
SmallVector< AArch64_IMM::ImmInsnModel, 4 > Insn
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
static bool isConstant(const MachineInstr &MI)
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG)
static bool isStore(int Opcode)
static bool isThumb(const MCSubtargetInfo &STI)
static SDValue LowerUADDSUBO_CARRY(SDValue Op, SelectionDAG &DAG)
static SDValue PerformExtractEltToVMOVRRD(SDNode *N, TargetLowering::DAGCombinerInfo &DCI)
static bool MatchingStackOffset(SDValue Arg, unsigned Offset, ISD::ArgFlagsTy Flags, MachineFrameInfo &MFI, const MachineRegisterInfo *MRI, const TargetInstrInfo *TII)
MatchingStackOffset - Return true if the given stack call argument is already available in the same p...
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 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 bool isLTorLE(ISD::CondCode CC)
static SDValue PerformVCMPCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue PerformMVEVMULLCombine(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *Subtarget)
static SDValue LowerSDIV_v4i16(SDValue N0, SDValue N1, const SDLoc &dl, SelectionDAG &DAG)
static SDValue 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)
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
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
Module.h This file contains the declarations for the Module class.
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())
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 bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
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[]
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
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
unsigned getPrefLoopLogAlignment() 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 ...
bool shouldSinkOperands(Instruction *I, SmallVectorImpl< Use * > &Ops) const override
Check if sinking I's operands to I's basic block is profitable, because the operands can be folded in...
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.
bool useLoadStackGuardNode() const override
If this function returns true, SelectionDAGBuilder emits a LOAD_STACK_GUARD node when it is lowering ...
const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const override
getRegClassFor - Return the register class that should be used for the specified value type.
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 parameter 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...
Align getStackAlignment() const
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.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
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).
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
TargetInstrInfo overrides.
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="")
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="")
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.
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args=std::nullopt, const Twine &Name="", MDNode *FPMathTag=nullptr)
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 Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
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.
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.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
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 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.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
const DebugLoc & getDebugLoc() const
This class provides iterator support for SDUse operands that use a specific SDNode.
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()
size_t use_size() const
Return the number of uses of this node.
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.
use_iterator use_begin() const
Provide iteration support to walk over all uses of an SDNode.
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.
void setFlags(SDNodeFlags NewFlags)
static use_iterator use_end()
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.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
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 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 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 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 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 getRegister(unsigned Reg, EVT VT)
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 getCopyToReg(SDValue Chain, const SDLoc &dl, unsigned Reg, SDValue N)
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 getCopyFromReg(SDValue Chain, const SDLoc &dl, unsigned Reg, EVT VT)
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.
const Use & getOperandUse(unsigned i) const
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Swift
Calling convention for Swift.
@ ARM_APCS
ARM Procedure Calling Standard (obsolete, but still used on some targets).
@ CFGuard_Check
Special calling convention on Windows for calling the Control Guard Check ICall funtion.
@ PreserveMost
Used for runtime calls that preserves most registers.
@ ARM_AAPCS
ARM Architecture Procedure Calling Standard calling convention (aka EABI).
@ CXX_FAST_TLS
Used for access functions.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ PreserveAll
Used for runtime calls that preserves (almost) all registers.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ SwiftTail
This follows the Swift calling convention in how arguments are passed but guarantees tail calls will ...
@ ARM_AAPCS_VFP
Same as ARM_AAPCS, but uses hard floating point ABI.
@ C
The default llvm calling convention, compatible with C.
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ STRICT_FSETCC
STRICT_FSETCC/STRICT_FSETCCS - Constrained versions of SETCC, used for floating-point operands only.
@ SET_FPENV
Sets the current floating-point environment.
@ MLOAD
Masked load and store - consecutive vector load and store operations with additional mask operand tha...
@ EH_SJLJ_LONGJMP
OUTCHAIN = EH_SJLJ_LONGJMP(INCHAIN, buffer) This corresponds to the eh.sjlj.longjmp intrinsic.
@ FGETSIGN
INT = FGETSIGN(FP) - Return the sign bit of the specified floating point value as an integer 0/1 valu...
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ BSWAP
Byte Swap and Counting operators.
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, ptr, val) 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.
@ 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.
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=std::nullopt)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
bool match(Val *V, const Pattern &P)
cst_pred_ty< is_zero_int > m_ZeroInt()
Match an integer 0 or a vector with all elements equal to 0.
TwoOps_match< V1_t, V2_t, Instruction::ShuffleVector > m_Shuffle(const V1_t &v1, const V2_t &v2)
Matches ShuffleVectorInst independently of mask value.
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
match_combine_or< CastInst_match< OpTy, ZExtInst >, CastInst_match< OpTy, SExtInst > > m_ZExtOrSExt(const OpTy &Op)
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
auto m_Undef()
Match an arbitrary undef constant.
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
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.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
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.
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)