10b57cec5SDimitry Andric //===-- AArch64SelectionDAGInfo.cpp - AArch64 SelectionDAG Info -----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the AArch64SelectionDAGInfo class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "AArch64TargetMachine.h"
140b57cec5SDimitry Andric using namespace llvm;
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric #define DEBUG_TYPE "aarch64-selectiondag-info"
170b57cec5SDimitry Andric
18*0fca6ea1SDimitry Andric static cl::opt<bool>
19*0fca6ea1SDimitry Andric LowerToSMERoutines("aarch64-lower-to-sme-routines", cl::Hidden,
20*0fca6ea1SDimitry Andric cl::desc("Enable AArch64 SME memory operations "
21*0fca6ea1SDimitry Andric "to lower to librt functions"),
22*0fca6ea1SDimitry Andric cl::init(true));
23*0fca6ea1SDimitry Andric
EmitMOPS(AArch64ISD::NodeType SDOpcode,SelectionDAG & DAG,const SDLoc & DL,SDValue Chain,SDValue Dst,SDValue SrcOrValue,SDValue Size,Align Alignment,bool isVolatile,MachinePointerInfo DstPtrInfo,MachinePointerInfo SrcPtrInfo) const241fd87a68SDimitry Andric SDValue AArch64SelectionDAGInfo::EmitMOPS(AArch64ISD::NodeType SDOpcode,
251fd87a68SDimitry Andric SelectionDAG &DAG, const SDLoc &DL,
261fd87a68SDimitry Andric SDValue Chain, SDValue Dst,
271fd87a68SDimitry Andric SDValue SrcOrValue, SDValue Size,
281fd87a68SDimitry Andric Align Alignment, bool isVolatile,
291fd87a68SDimitry Andric MachinePointerInfo DstPtrInfo,
301fd87a68SDimitry Andric MachinePointerInfo SrcPtrInfo) const {
311fd87a68SDimitry Andric
321fd87a68SDimitry Andric // Get the constant size of the copy/set.
331fd87a68SDimitry Andric uint64_t ConstSize = 0;
341fd87a68SDimitry Andric if (auto *C = dyn_cast<ConstantSDNode>(Size))
351fd87a68SDimitry Andric ConstSize = C->getZExtValue();
361fd87a68SDimitry Andric
371fd87a68SDimitry Andric const bool IsSet = SDOpcode == AArch64ISD::MOPS_MEMSET ||
381fd87a68SDimitry Andric SDOpcode == AArch64ISD::MOPS_MEMSET_TAGGING;
391fd87a68SDimitry Andric
401fd87a68SDimitry Andric const auto MachineOpcode = [&]() {
411fd87a68SDimitry Andric switch (SDOpcode) {
421fd87a68SDimitry Andric case AArch64ISD::MOPS_MEMSET:
431fd87a68SDimitry Andric return AArch64::MOPSMemorySetPseudo;
441fd87a68SDimitry Andric case AArch64ISD::MOPS_MEMSET_TAGGING:
451fd87a68SDimitry Andric return AArch64::MOPSMemorySetTaggingPseudo;
461fd87a68SDimitry Andric case AArch64ISD::MOPS_MEMCOPY:
471fd87a68SDimitry Andric return AArch64::MOPSMemoryCopyPseudo;
481fd87a68SDimitry Andric case AArch64ISD::MOPS_MEMMOVE:
491fd87a68SDimitry Andric return AArch64::MOPSMemoryMovePseudo;
501fd87a68SDimitry Andric default:
511fd87a68SDimitry Andric llvm_unreachable("Unhandled MOPS ISD Opcode");
521fd87a68SDimitry Andric }
531fd87a68SDimitry Andric }();
541fd87a68SDimitry Andric
551fd87a68SDimitry Andric MachineFunction &MF = DAG.getMachineFunction();
561fd87a68SDimitry Andric
575f757f3fSDimitry Andric auto Vol =
585f757f3fSDimitry Andric isVolatile ? MachineMemOperand::MOVolatile : MachineMemOperand::MONone;
595f757f3fSDimitry Andric auto DstFlags = MachineMemOperand::MOStore | Vol;
601fd87a68SDimitry Andric auto *DstOp =
615f757f3fSDimitry Andric MF.getMachineMemOperand(DstPtrInfo, DstFlags, ConstSize, Alignment);
621fd87a68SDimitry Andric
631fd87a68SDimitry Andric if (IsSet) {
645f757f3fSDimitry Andric // Extend value to i64, if required.
651fd87a68SDimitry Andric if (SrcOrValue.getValueType() != MVT::i64)
661fd87a68SDimitry Andric SrcOrValue = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, SrcOrValue);
671fd87a68SDimitry Andric SDValue Ops[] = {Dst, Size, SrcOrValue, Chain};
681fd87a68SDimitry Andric const EVT ResultTys[] = {MVT::i64, MVT::i64, MVT::Other};
691fd87a68SDimitry Andric MachineSDNode *Node = DAG.getMachineNode(MachineOpcode, DL, ResultTys, Ops);
701fd87a68SDimitry Andric DAG.setNodeMemRefs(Node, {DstOp});
711fd87a68SDimitry Andric return SDValue(Node, 2);
721fd87a68SDimitry Andric } else {
731fd87a68SDimitry Andric SDValue Ops[] = {Dst, SrcOrValue, Size, Chain};
741fd87a68SDimitry Andric const EVT ResultTys[] = {MVT::i64, MVT::i64, MVT::i64, MVT::Other};
751fd87a68SDimitry Andric MachineSDNode *Node = DAG.getMachineNode(MachineOpcode, DL, ResultTys, Ops);
765f757f3fSDimitry Andric
775f757f3fSDimitry Andric auto SrcFlags = MachineMemOperand::MOLoad | Vol;
785f757f3fSDimitry Andric auto *SrcOp =
795f757f3fSDimitry Andric MF.getMachineMemOperand(SrcPtrInfo, SrcFlags, ConstSize, Alignment);
801fd87a68SDimitry Andric DAG.setNodeMemRefs(Node, {DstOp, SrcOp});
811fd87a68SDimitry Andric return SDValue(Node, 3);
821fd87a68SDimitry Andric }
831fd87a68SDimitry Andric }
841fd87a68SDimitry Andric
EmitStreamingCompatibleMemLibCall(SelectionDAG & DAG,const SDLoc & DL,SDValue Chain,SDValue Dst,SDValue Src,SDValue Size,RTLIB::Libcall LC) const85*0fca6ea1SDimitry Andric SDValue AArch64SelectionDAGInfo::EmitStreamingCompatibleMemLibCall(
86*0fca6ea1SDimitry Andric SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Dst, SDValue Src,
87*0fca6ea1SDimitry Andric SDValue Size, RTLIB::Libcall LC) const {
88*0fca6ea1SDimitry Andric const AArch64Subtarget &STI =
89*0fca6ea1SDimitry Andric DAG.getMachineFunction().getSubtarget<AArch64Subtarget>();
90*0fca6ea1SDimitry Andric const AArch64TargetLowering *TLI = STI.getTargetLowering();
91*0fca6ea1SDimitry Andric SDValue Symbol;
92*0fca6ea1SDimitry Andric TargetLowering::ArgListEntry DstEntry;
93*0fca6ea1SDimitry Andric DstEntry.Ty = PointerType::getUnqual(*DAG.getContext());
94*0fca6ea1SDimitry Andric DstEntry.Node = Dst;
95*0fca6ea1SDimitry Andric TargetLowering::ArgListTy Args;
96*0fca6ea1SDimitry Andric Args.push_back(DstEntry);
97*0fca6ea1SDimitry Andric EVT PointerVT = TLI->getPointerTy(DAG.getDataLayout());
98*0fca6ea1SDimitry Andric
99*0fca6ea1SDimitry Andric switch (LC) {
100*0fca6ea1SDimitry Andric case RTLIB::MEMCPY: {
101*0fca6ea1SDimitry Andric TargetLowering::ArgListEntry Entry;
102*0fca6ea1SDimitry Andric Entry.Ty = PointerType::getUnqual(*DAG.getContext());
103*0fca6ea1SDimitry Andric Symbol = DAG.getExternalSymbol("__arm_sc_memcpy", PointerVT);
104*0fca6ea1SDimitry Andric Entry.Node = Src;
105*0fca6ea1SDimitry Andric Args.push_back(Entry);
106*0fca6ea1SDimitry Andric break;
107*0fca6ea1SDimitry Andric }
108*0fca6ea1SDimitry Andric case RTLIB::MEMMOVE: {
109*0fca6ea1SDimitry Andric TargetLowering::ArgListEntry Entry;
110*0fca6ea1SDimitry Andric Entry.Ty = PointerType::getUnqual(*DAG.getContext());
111*0fca6ea1SDimitry Andric Symbol = DAG.getExternalSymbol("__arm_sc_memmove", PointerVT);
112*0fca6ea1SDimitry Andric Entry.Node = Src;
113*0fca6ea1SDimitry Andric Args.push_back(Entry);
114*0fca6ea1SDimitry Andric break;
115*0fca6ea1SDimitry Andric }
116*0fca6ea1SDimitry Andric case RTLIB::MEMSET: {
117*0fca6ea1SDimitry Andric TargetLowering::ArgListEntry Entry;
118*0fca6ea1SDimitry Andric Entry.Ty = Type::getInt32Ty(*DAG.getContext());
119*0fca6ea1SDimitry Andric Symbol = DAG.getExternalSymbol("__arm_sc_memset", PointerVT);
120*0fca6ea1SDimitry Andric Src = DAG.getZExtOrTrunc(Src, DL, MVT::i32);
121*0fca6ea1SDimitry Andric Entry.Node = Src;
122*0fca6ea1SDimitry Andric Args.push_back(Entry);
123*0fca6ea1SDimitry Andric break;
124*0fca6ea1SDimitry Andric }
125*0fca6ea1SDimitry Andric default:
126*0fca6ea1SDimitry Andric return SDValue();
127*0fca6ea1SDimitry Andric }
128*0fca6ea1SDimitry Andric
129*0fca6ea1SDimitry Andric TargetLowering::ArgListEntry SizeEntry;
130*0fca6ea1SDimitry Andric SizeEntry.Node = Size;
131*0fca6ea1SDimitry Andric SizeEntry.Ty = DAG.getDataLayout().getIntPtrType(*DAG.getContext());
132*0fca6ea1SDimitry Andric Args.push_back(SizeEntry);
133*0fca6ea1SDimitry Andric assert(Symbol->getOpcode() == ISD::ExternalSymbol &&
134*0fca6ea1SDimitry Andric "Function name is not set");
135*0fca6ea1SDimitry Andric
136*0fca6ea1SDimitry Andric TargetLowering::CallLoweringInfo CLI(DAG);
137*0fca6ea1SDimitry Andric PointerType *RetTy = PointerType::getUnqual(*DAG.getContext());
138*0fca6ea1SDimitry Andric CLI.setDebugLoc(DL).setChain(Chain).setLibCallee(
139*0fca6ea1SDimitry Andric TLI->getLibcallCallingConv(LC), RetTy, Symbol, std::move(Args));
140*0fca6ea1SDimitry Andric return TLI->LowerCallTo(CLI).second;
141*0fca6ea1SDimitry Andric }
142*0fca6ea1SDimitry Andric
EmitTargetCodeForMemcpy(SelectionDAG & DAG,const SDLoc & DL,SDValue Chain,SDValue Dst,SDValue Src,SDValue Size,Align Alignment,bool isVolatile,bool AlwaysInline,MachinePointerInfo DstPtrInfo,MachinePointerInfo SrcPtrInfo) const1431fd87a68SDimitry Andric SDValue AArch64SelectionDAGInfo::EmitTargetCodeForMemcpy(
1441fd87a68SDimitry Andric SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Dst, SDValue Src,
1451fd87a68SDimitry Andric SDValue Size, Align Alignment, bool isVolatile, bool AlwaysInline,
1461fd87a68SDimitry Andric MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const {
1471fd87a68SDimitry Andric const AArch64Subtarget &STI =
1481fd87a68SDimitry Andric DAG.getMachineFunction().getSubtarget<AArch64Subtarget>();
149*0fca6ea1SDimitry Andric
1501fd87a68SDimitry Andric if (STI.hasMOPS())
1511fd87a68SDimitry Andric return EmitMOPS(AArch64ISD::MOPS_MEMCOPY, DAG, DL, Chain, Dst, Src, Size,
1521fd87a68SDimitry Andric Alignment, isVolatile, DstPtrInfo, SrcPtrInfo);
153*0fca6ea1SDimitry Andric
154*0fca6ea1SDimitry Andric SMEAttrs Attrs(DAG.getMachineFunction().getFunction());
155*0fca6ea1SDimitry Andric if (LowerToSMERoutines && !Attrs.hasNonStreamingInterfaceAndBody())
156*0fca6ea1SDimitry Andric return EmitStreamingCompatibleMemLibCall(DAG, DL, Chain, Dst, Src, Size,
157*0fca6ea1SDimitry Andric RTLIB::MEMCPY);
1581fd87a68SDimitry Andric return SDValue();
1591fd87a68SDimitry Andric }
1601fd87a68SDimitry Andric
EmitTargetCodeForMemset(SelectionDAG & DAG,const SDLoc & dl,SDValue Chain,SDValue Dst,SDValue Src,SDValue Size,Align Alignment,bool isVolatile,bool AlwaysInline,MachinePointerInfo DstPtrInfo) const1610b57cec5SDimitry Andric SDValue AArch64SelectionDAGInfo::EmitTargetCodeForMemset(
1620b57cec5SDimitry Andric SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src,
16381ad6265SDimitry Andric SDValue Size, Align Alignment, bool isVolatile, bool AlwaysInline,
1640b57cec5SDimitry Andric MachinePointerInfo DstPtrInfo) const {
1651fd87a68SDimitry Andric const AArch64Subtarget &STI =
1661fd87a68SDimitry Andric DAG.getMachineFunction().getSubtarget<AArch64Subtarget>();
1671fd87a68SDimitry Andric
168*0fca6ea1SDimitry Andric if (STI.hasMOPS())
1691fd87a68SDimitry Andric return EmitMOPS(AArch64ISD::MOPS_MEMSET, DAG, dl, Chain, Dst, Src, Size,
1701fd87a68SDimitry Andric Alignment, isVolatile, DstPtrInfo, MachinePointerInfo{});
171*0fca6ea1SDimitry Andric
172*0fca6ea1SDimitry Andric SMEAttrs Attrs(DAG.getMachineFunction().getFunction());
173*0fca6ea1SDimitry Andric if (LowerToSMERoutines && !Attrs.hasNonStreamingInterfaceAndBody())
174*0fca6ea1SDimitry Andric return EmitStreamingCompatibleMemLibCall(DAG, dl, Chain, Dst, Src, Size,
175*0fca6ea1SDimitry Andric RTLIB::MEMSET);
1760b57cec5SDimitry Andric return SDValue();
1770b57cec5SDimitry Andric }
1780b57cec5SDimitry Andric
EmitTargetCodeForMemmove(SelectionDAG & DAG,const SDLoc & dl,SDValue Chain,SDValue Dst,SDValue Src,SDValue Size,Align Alignment,bool isVolatile,MachinePointerInfo DstPtrInfo,MachinePointerInfo SrcPtrInfo) const1791fd87a68SDimitry Andric SDValue AArch64SelectionDAGInfo::EmitTargetCodeForMemmove(
1801fd87a68SDimitry Andric SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src,
1811fd87a68SDimitry Andric SDValue Size, Align Alignment, bool isVolatile,
1821fd87a68SDimitry Andric MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const {
1831fd87a68SDimitry Andric const AArch64Subtarget &STI =
1841fd87a68SDimitry Andric DAG.getMachineFunction().getSubtarget<AArch64Subtarget>();
185*0fca6ea1SDimitry Andric
186*0fca6ea1SDimitry Andric if (STI.hasMOPS())
1871fd87a68SDimitry Andric return EmitMOPS(AArch64ISD::MOPS_MEMMOVE, DAG, dl, Chain, Dst, Src, Size,
1881fd87a68SDimitry Andric Alignment, isVolatile, DstPtrInfo, SrcPtrInfo);
189*0fca6ea1SDimitry Andric
190*0fca6ea1SDimitry Andric SMEAttrs Attrs(DAG.getMachineFunction().getFunction());
191*0fca6ea1SDimitry Andric if (LowerToSMERoutines && !Attrs.hasNonStreamingInterfaceAndBody())
192*0fca6ea1SDimitry Andric return EmitStreamingCompatibleMemLibCall(DAG, dl, Chain, Dst, Src, Size,
193*0fca6ea1SDimitry Andric RTLIB::MEMMOVE);
1941fd87a68SDimitry Andric return SDValue();
1951fd87a68SDimitry Andric }
1961fd87a68SDimitry Andric
1970b57cec5SDimitry Andric static const int kSetTagLoopThreshold = 176;
1980b57cec5SDimitry Andric
EmitUnrolledSetTag(SelectionDAG & DAG,const SDLoc & dl,SDValue Chain,SDValue Ptr,uint64_t ObjSize,const MachineMemOperand * BaseMemOperand,bool ZeroData)1990b57cec5SDimitry Andric static SDValue EmitUnrolledSetTag(SelectionDAG &DAG, const SDLoc &dl,
2000b57cec5SDimitry Andric SDValue Chain, SDValue Ptr, uint64_t ObjSize,
2010b57cec5SDimitry Andric const MachineMemOperand *BaseMemOperand,
2020b57cec5SDimitry Andric bool ZeroData) {
2030b57cec5SDimitry Andric MachineFunction &MF = DAG.getMachineFunction();
2040b57cec5SDimitry Andric unsigned ObjSizeScaled = ObjSize / 16;
2050b57cec5SDimitry Andric
2060b57cec5SDimitry Andric SDValue TagSrc = Ptr;
2070b57cec5SDimitry Andric if (Ptr.getOpcode() == ISD::FrameIndex) {
2080b57cec5SDimitry Andric int FI = cast<FrameIndexSDNode>(Ptr)->getIndex();
2090b57cec5SDimitry Andric Ptr = DAG.getTargetFrameIndex(FI, MVT::i64);
2100b57cec5SDimitry Andric // A frame index operand may end up as [SP + offset] => it is fine to use SP
2110b57cec5SDimitry Andric // register as the tag source.
2120b57cec5SDimitry Andric TagSrc = DAG.getRegister(AArch64::SP, MVT::i64);
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric
2150b57cec5SDimitry Andric const unsigned OpCode1 = ZeroData ? AArch64ISD::STZG : AArch64ISD::STG;
2160b57cec5SDimitry Andric const unsigned OpCode2 = ZeroData ? AArch64ISD::STZ2G : AArch64ISD::ST2G;
2170b57cec5SDimitry Andric
2180b57cec5SDimitry Andric SmallVector<SDValue, 8> OutChains;
2190b57cec5SDimitry Andric unsigned OffsetScaled = 0;
2200b57cec5SDimitry Andric while (OffsetScaled < ObjSizeScaled) {
2210b57cec5SDimitry Andric if (ObjSizeScaled - OffsetScaled >= 2) {
2225f757f3fSDimitry Andric SDValue AddrNode = DAG.getMemBasePlusOffset(
2235f757f3fSDimitry Andric Ptr, TypeSize::getFixed(OffsetScaled * 16), dl);
2240b57cec5SDimitry Andric SDValue St = DAG.getMemIntrinsicNode(
2250b57cec5SDimitry Andric OpCode2, dl, DAG.getVTList(MVT::Other),
2260b57cec5SDimitry Andric {Chain, TagSrc, AddrNode},
2270b57cec5SDimitry Andric MVT::v4i64,
2280b57cec5SDimitry Andric MF.getMachineMemOperand(BaseMemOperand, OffsetScaled * 16, 16 * 2));
2290b57cec5SDimitry Andric OffsetScaled += 2;
2300b57cec5SDimitry Andric OutChains.push_back(St);
2310b57cec5SDimitry Andric continue;
2320b57cec5SDimitry Andric }
2330b57cec5SDimitry Andric
2340b57cec5SDimitry Andric if (ObjSizeScaled - OffsetScaled > 0) {
2355f757f3fSDimitry Andric SDValue AddrNode = DAG.getMemBasePlusOffset(
2365f757f3fSDimitry Andric Ptr, TypeSize::getFixed(OffsetScaled * 16), dl);
2370b57cec5SDimitry Andric SDValue St = DAG.getMemIntrinsicNode(
2380b57cec5SDimitry Andric OpCode1, dl, DAG.getVTList(MVT::Other),
2390b57cec5SDimitry Andric {Chain, TagSrc, AddrNode},
2400b57cec5SDimitry Andric MVT::v2i64,
2410b57cec5SDimitry Andric MF.getMachineMemOperand(BaseMemOperand, OffsetScaled * 16, 16));
2420b57cec5SDimitry Andric OffsetScaled += 1;
2430b57cec5SDimitry Andric OutChains.push_back(St);
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric }
2460b57cec5SDimitry Andric
2470b57cec5SDimitry Andric SDValue Res = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
2480b57cec5SDimitry Andric return Res;
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric
EmitTargetCodeForSetTag(SelectionDAG & DAG,const SDLoc & dl,SDValue Chain,SDValue Addr,SDValue Size,MachinePointerInfo DstPtrInfo,bool ZeroData) const2510b57cec5SDimitry Andric SDValue AArch64SelectionDAGInfo::EmitTargetCodeForSetTag(
2520b57cec5SDimitry Andric SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Addr,
2530b57cec5SDimitry Andric SDValue Size, MachinePointerInfo DstPtrInfo, bool ZeroData) const {
2541db9f3b2SDimitry Andric uint64_t ObjSize = Size->getAsZExtVal();
2550b57cec5SDimitry Andric assert(ObjSize % 16 == 0);
2560b57cec5SDimitry Andric
2570b57cec5SDimitry Andric MachineFunction &MF = DAG.getMachineFunction();
2580b57cec5SDimitry Andric MachineMemOperand *BaseMemOperand = MF.getMachineMemOperand(
2595ffd83dbSDimitry Andric DstPtrInfo, MachineMemOperand::MOStore, ObjSize, Align(16));
2600b57cec5SDimitry Andric
2610b57cec5SDimitry Andric bool UseSetTagRangeLoop =
2620b57cec5SDimitry Andric kSetTagLoopThreshold >= 0 && (int)ObjSize >= kSetTagLoopThreshold;
2630b57cec5SDimitry Andric if (!UseSetTagRangeLoop)
2640b57cec5SDimitry Andric return EmitUnrolledSetTag(DAG, dl, Chain, Addr, ObjSize, BaseMemOperand,
2650b57cec5SDimitry Andric ZeroData);
2660b57cec5SDimitry Andric
2670b57cec5SDimitry Andric const EVT ResTys[] = {MVT::i64, MVT::i64, MVT::Other};
2685ffd83dbSDimitry Andric
2695ffd83dbSDimitry Andric unsigned Opcode;
2705ffd83dbSDimitry Andric if (Addr.getOpcode() == ISD::FrameIndex) {
2715ffd83dbSDimitry Andric int FI = cast<FrameIndexSDNode>(Addr)->getIndex();
2725ffd83dbSDimitry Andric Addr = DAG.getTargetFrameIndex(FI, MVT::i64);
2735ffd83dbSDimitry Andric Opcode = ZeroData ? AArch64::STZGloop : AArch64::STGloop;
2745ffd83dbSDimitry Andric } else {
2755ffd83dbSDimitry Andric Opcode = ZeroData ? AArch64::STZGloop_wback : AArch64::STGloop_wback;
2765ffd83dbSDimitry Andric }
2775ffd83dbSDimitry Andric SDValue Ops[] = {DAG.getTargetConstant(ObjSize, dl, MVT::i64), Addr, Chain};
2785ffd83dbSDimitry Andric SDNode *St = DAG.getMachineNode(Opcode, dl, ResTys, Ops);
2790b57cec5SDimitry Andric
2800b57cec5SDimitry Andric DAG.setNodeMemRefs(cast<MachineSDNode>(St), {BaseMemOperand});
2810b57cec5SDimitry Andric return SDValue(St, 2);
2820b57cec5SDimitry Andric }
283