xref: /aosp_15_r20/external/llvm/lib/Target/X86/X86SelectionDAGInfo.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- X86SelectionDAGInfo.cpp - X86 SelectionDAG Info -------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file implements the X86SelectionDAGInfo class.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker 
14*9880d681SAndroid Build Coastguard Worker #include "X86InstrInfo.h"
15*9880d681SAndroid Build Coastguard Worker #include "X86ISelLowering.h"
16*9880d681SAndroid Build Coastguard Worker #include "X86RegisterInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "X86Subtarget.h"
18*9880d681SAndroid Build Coastguard Worker #include "X86SelectionDAGInfo.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/SelectionDAG.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DerivedTypes.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetLowering.h"
22*9880d681SAndroid Build Coastguard Worker 
23*9880d681SAndroid Build Coastguard Worker using namespace llvm;
24*9880d681SAndroid Build Coastguard Worker 
25*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "x86-selectiondag-info"
26*9880d681SAndroid Build Coastguard Worker 
isBaseRegConflictPossible(SelectionDAG & DAG,ArrayRef<MCPhysReg> ClobberSet) const27*9880d681SAndroid Build Coastguard Worker bool X86SelectionDAGInfo::isBaseRegConflictPossible(
28*9880d681SAndroid Build Coastguard Worker     SelectionDAG &DAG, ArrayRef<MCPhysReg> ClobberSet) const {
29*9880d681SAndroid Build Coastguard Worker   // We cannot use TRI->hasBasePointer() until *after* we select all basic
30*9880d681SAndroid Build Coastguard Worker   // blocks.  Legalization may introduce new stack temporaries with large
31*9880d681SAndroid Build Coastguard Worker   // alignment requirements.  Fall back to generic code if there are any
32*9880d681SAndroid Build Coastguard Worker   // dynamic stack adjustments (hopefully rare) and the base pointer would
33*9880d681SAndroid Build Coastguard Worker   // conflict if we had to use it.
34*9880d681SAndroid Build Coastguard Worker   MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
35*9880d681SAndroid Build Coastguard Worker   if (!MFI->hasVarSizedObjects() && !MFI->hasOpaqueSPAdjustment())
36*9880d681SAndroid Build Coastguard Worker     return false;
37*9880d681SAndroid Build Coastguard Worker 
38*9880d681SAndroid Build Coastguard Worker   const X86RegisterInfo *TRI = static_cast<const X86RegisterInfo *>(
39*9880d681SAndroid Build Coastguard Worker       DAG.getSubtarget().getRegisterInfo());
40*9880d681SAndroid Build Coastguard Worker   unsigned BaseReg = TRI->getBaseRegister();
41*9880d681SAndroid Build Coastguard Worker   for (unsigned R : ClobberSet)
42*9880d681SAndroid Build Coastguard Worker     if (BaseReg == R)
43*9880d681SAndroid Build Coastguard Worker       return true;
44*9880d681SAndroid Build Coastguard Worker   return false;
45*9880d681SAndroid Build Coastguard Worker }
46*9880d681SAndroid Build Coastguard Worker 
EmitTargetCodeForMemset(SelectionDAG & DAG,const SDLoc & dl,SDValue Chain,SDValue Dst,SDValue Src,SDValue Size,unsigned Align,bool isVolatile,MachinePointerInfo DstPtrInfo) const47*9880d681SAndroid Build Coastguard Worker SDValue X86SelectionDAGInfo::EmitTargetCodeForMemset(
48*9880d681SAndroid Build Coastguard Worker     SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src,
49*9880d681SAndroid Build Coastguard Worker     SDValue Size, unsigned Align, bool isVolatile,
50*9880d681SAndroid Build Coastguard Worker     MachinePointerInfo DstPtrInfo) const {
51*9880d681SAndroid Build Coastguard Worker   ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
52*9880d681SAndroid Build Coastguard Worker   const X86Subtarget &Subtarget =
53*9880d681SAndroid Build Coastguard Worker       DAG.getMachineFunction().getSubtarget<X86Subtarget>();
54*9880d681SAndroid Build Coastguard Worker 
55*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
56*9880d681SAndroid Build Coastguard Worker   // If the base register might conflict with our physical registers, bail out.
57*9880d681SAndroid Build Coastguard Worker   const MCPhysReg ClobberSet[] = {X86::RCX, X86::RAX, X86::RDI,
58*9880d681SAndroid Build Coastguard Worker                                   X86::ECX, X86::EAX, X86::EDI};
59*9880d681SAndroid Build Coastguard Worker   assert(!isBaseRegConflictPossible(DAG, ClobberSet));
60*9880d681SAndroid Build Coastguard Worker #endif
61*9880d681SAndroid Build Coastguard Worker 
62*9880d681SAndroid Build Coastguard Worker   // If to a segment-relative address space, use the default lowering.
63*9880d681SAndroid Build Coastguard Worker   if (DstPtrInfo.getAddrSpace() >= 256)
64*9880d681SAndroid Build Coastguard Worker     return SDValue();
65*9880d681SAndroid Build Coastguard Worker 
66*9880d681SAndroid Build Coastguard Worker   // If not DWORD aligned or size is more than the threshold, call the library.
67*9880d681SAndroid Build Coastguard Worker   // The libc version is likely to be faster for these cases. It can use the
68*9880d681SAndroid Build Coastguard Worker   // address value and run time information about the CPU.
69*9880d681SAndroid Build Coastguard Worker   if ((Align & 3) != 0 || !ConstantSize ||
70*9880d681SAndroid Build Coastguard Worker       ConstantSize->getZExtValue() > Subtarget.getMaxInlineSizeThreshold()) {
71*9880d681SAndroid Build Coastguard Worker     // Check to see if there is a specialized entry-point for memory zeroing.
72*9880d681SAndroid Build Coastguard Worker     ConstantSDNode *V = dyn_cast<ConstantSDNode>(Src);
73*9880d681SAndroid Build Coastguard Worker 
74*9880d681SAndroid Build Coastguard Worker     if (const char *bzeroEntry = V &&
75*9880d681SAndroid Build Coastguard Worker         V->isNullValue() ? Subtarget.getBZeroEntry() : nullptr) {
76*9880d681SAndroid Build Coastguard Worker       const TargetLowering &TLI = DAG.getTargetLoweringInfo();
77*9880d681SAndroid Build Coastguard Worker       EVT IntPtr = TLI.getPointerTy(DAG.getDataLayout());
78*9880d681SAndroid Build Coastguard Worker       Type *IntPtrTy = DAG.getDataLayout().getIntPtrType(*DAG.getContext());
79*9880d681SAndroid Build Coastguard Worker       TargetLowering::ArgListTy Args;
80*9880d681SAndroid Build Coastguard Worker       TargetLowering::ArgListEntry Entry;
81*9880d681SAndroid Build Coastguard Worker       Entry.Node = Dst;
82*9880d681SAndroid Build Coastguard Worker       Entry.Ty = IntPtrTy;
83*9880d681SAndroid Build Coastguard Worker       Args.push_back(Entry);
84*9880d681SAndroid Build Coastguard Worker       Entry.Node = Size;
85*9880d681SAndroid Build Coastguard Worker       Args.push_back(Entry);
86*9880d681SAndroid Build Coastguard Worker 
87*9880d681SAndroid Build Coastguard Worker       TargetLowering::CallLoweringInfo CLI(DAG);
88*9880d681SAndroid Build Coastguard Worker       CLI.setDebugLoc(dl).setChain(Chain)
89*9880d681SAndroid Build Coastguard Worker         .setCallee(CallingConv::C, Type::getVoidTy(*DAG.getContext()),
90*9880d681SAndroid Build Coastguard Worker                    DAG.getExternalSymbol(bzeroEntry, IntPtr), std::move(Args))
91*9880d681SAndroid Build Coastguard Worker         .setDiscardResult();
92*9880d681SAndroid Build Coastguard Worker 
93*9880d681SAndroid Build Coastguard Worker       std::pair<SDValue,SDValue> CallResult = TLI.LowerCallTo(CLI);
94*9880d681SAndroid Build Coastguard Worker       return CallResult.second;
95*9880d681SAndroid Build Coastguard Worker     }
96*9880d681SAndroid Build Coastguard Worker 
97*9880d681SAndroid Build Coastguard Worker     // Otherwise have the target-independent code call memset.
98*9880d681SAndroid Build Coastguard Worker     return SDValue();
99*9880d681SAndroid Build Coastguard Worker   }
100*9880d681SAndroid Build Coastguard Worker 
101*9880d681SAndroid Build Coastguard Worker   uint64_t SizeVal = ConstantSize->getZExtValue();
102*9880d681SAndroid Build Coastguard Worker   SDValue InFlag;
103*9880d681SAndroid Build Coastguard Worker   EVT AVT;
104*9880d681SAndroid Build Coastguard Worker   SDValue Count;
105*9880d681SAndroid Build Coastguard Worker   ConstantSDNode *ValC = dyn_cast<ConstantSDNode>(Src);
106*9880d681SAndroid Build Coastguard Worker   unsigned BytesLeft = 0;
107*9880d681SAndroid Build Coastguard Worker   bool TwoRepStos = false;
108*9880d681SAndroid Build Coastguard Worker   if (ValC) {
109*9880d681SAndroid Build Coastguard Worker     unsigned ValReg;
110*9880d681SAndroid Build Coastguard Worker     uint64_t Val = ValC->getZExtValue() & 255;
111*9880d681SAndroid Build Coastguard Worker 
112*9880d681SAndroid Build Coastguard Worker     // If the value is a constant, then we can potentially use larger sets.
113*9880d681SAndroid Build Coastguard Worker     switch (Align & 3) {
114*9880d681SAndroid Build Coastguard Worker     case 2:   // WORD aligned
115*9880d681SAndroid Build Coastguard Worker       AVT = MVT::i16;
116*9880d681SAndroid Build Coastguard Worker       ValReg = X86::AX;
117*9880d681SAndroid Build Coastguard Worker       Val = (Val << 8) | Val;
118*9880d681SAndroid Build Coastguard Worker       break;
119*9880d681SAndroid Build Coastguard Worker     case 0:  // DWORD aligned
120*9880d681SAndroid Build Coastguard Worker       AVT = MVT::i32;
121*9880d681SAndroid Build Coastguard Worker       ValReg = X86::EAX;
122*9880d681SAndroid Build Coastguard Worker       Val = (Val << 8)  | Val;
123*9880d681SAndroid Build Coastguard Worker       Val = (Val << 16) | Val;
124*9880d681SAndroid Build Coastguard Worker       if (Subtarget.is64Bit() && ((Align & 0x7) == 0)) {  // QWORD aligned
125*9880d681SAndroid Build Coastguard Worker         AVT = MVT::i64;
126*9880d681SAndroid Build Coastguard Worker         ValReg = X86::RAX;
127*9880d681SAndroid Build Coastguard Worker         Val = (Val << 32) | Val;
128*9880d681SAndroid Build Coastguard Worker       }
129*9880d681SAndroid Build Coastguard Worker       break;
130*9880d681SAndroid Build Coastguard Worker     default:  // Byte aligned
131*9880d681SAndroid Build Coastguard Worker       AVT = MVT::i8;
132*9880d681SAndroid Build Coastguard Worker       ValReg = X86::AL;
133*9880d681SAndroid Build Coastguard Worker       Count = DAG.getIntPtrConstant(SizeVal, dl);
134*9880d681SAndroid Build Coastguard Worker       break;
135*9880d681SAndroid Build Coastguard Worker     }
136*9880d681SAndroid Build Coastguard Worker 
137*9880d681SAndroid Build Coastguard Worker     if (AVT.bitsGT(MVT::i8)) {
138*9880d681SAndroid Build Coastguard Worker       unsigned UBytes = AVT.getSizeInBits() / 8;
139*9880d681SAndroid Build Coastguard Worker       Count = DAG.getIntPtrConstant(SizeVal / UBytes, dl);
140*9880d681SAndroid Build Coastguard Worker       BytesLeft = SizeVal % UBytes;
141*9880d681SAndroid Build Coastguard Worker     }
142*9880d681SAndroid Build Coastguard Worker 
143*9880d681SAndroid Build Coastguard Worker     Chain = DAG.getCopyToReg(Chain, dl, ValReg, DAG.getConstant(Val, dl, AVT),
144*9880d681SAndroid Build Coastguard Worker                              InFlag);
145*9880d681SAndroid Build Coastguard Worker     InFlag = Chain.getValue(1);
146*9880d681SAndroid Build Coastguard Worker   } else {
147*9880d681SAndroid Build Coastguard Worker     AVT = MVT::i8;
148*9880d681SAndroid Build Coastguard Worker     Count  = DAG.getIntPtrConstant(SizeVal, dl);
149*9880d681SAndroid Build Coastguard Worker     Chain  = DAG.getCopyToReg(Chain, dl, X86::AL, Src, InFlag);
150*9880d681SAndroid Build Coastguard Worker     InFlag = Chain.getValue(1);
151*9880d681SAndroid Build Coastguard Worker   }
152*9880d681SAndroid Build Coastguard Worker 
153*9880d681SAndroid Build Coastguard Worker   Chain = DAG.getCopyToReg(Chain, dl, Subtarget.is64Bit() ? X86::RCX : X86::ECX,
154*9880d681SAndroid Build Coastguard Worker                            Count, InFlag);
155*9880d681SAndroid Build Coastguard Worker   InFlag = Chain.getValue(1);
156*9880d681SAndroid Build Coastguard Worker   Chain = DAG.getCopyToReg(Chain, dl, Subtarget.is64Bit() ? X86::RDI : X86::EDI,
157*9880d681SAndroid Build Coastguard Worker                            Dst, InFlag);
158*9880d681SAndroid Build Coastguard Worker   InFlag = Chain.getValue(1);
159*9880d681SAndroid Build Coastguard Worker 
160*9880d681SAndroid Build Coastguard Worker   SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Glue);
161*9880d681SAndroid Build Coastguard Worker   SDValue Ops[] = { Chain, DAG.getValueType(AVT), InFlag };
162*9880d681SAndroid Build Coastguard Worker   Chain = DAG.getNode(X86ISD::REP_STOS, dl, Tys, Ops);
163*9880d681SAndroid Build Coastguard Worker 
164*9880d681SAndroid Build Coastguard Worker   if (TwoRepStos) {
165*9880d681SAndroid Build Coastguard Worker     InFlag = Chain.getValue(1);
166*9880d681SAndroid Build Coastguard Worker     Count  = Size;
167*9880d681SAndroid Build Coastguard Worker     EVT CVT = Count.getValueType();
168*9880d681SAndroid Build Coastguard Worker     SDValue Left = DAG.getNode(ISD::AND, dl, CVT, Count,
169*9880d681SAndroid Build Coastguard Worker                                DAG.getConstant((AVT == MVT::i64) ? 7 : 3, dl,
170*9880d681SAndroid Build Coastguard Worker                                                CVT));
171*9880d681SAndroid Build Coastguard Worker     Chain = DAG.getCopyToReg(Chain, dl, (CVT == MVT::i64) ? X86::RCX : X86::ECX,
172*9880d681SAndroid Build Coastguard Worker                              Left, InFlag);
173*9880d681SAndroid Build Coastguard Worker     InFlag = Chain.getValue(1);
174*9880d681SAndroid Build Coastguard Worker     Tys = DAG.getVTList(MVT::Other, MVT::Glue);
175*9880d681SAndroid Build Coastguard Worker     SDValue Ops[] = { Chain, DAG.getValueType(MVT::i8), InFlag };
176*9880d681SAndroid Build Coastguard Worker     Chain = DAG.getNode(X86ISD::REP_STOS, dl, Tys, Ops);
177*9880d681SAndroid Build Coastguard Worker   } else if (BytesLeft) {
178*9880d681SAndroid Build Coastguard Worker     // Handle the last 1 - 7 bytes.
179*9880d681SAndroid Build Coastguard Worker     unsigned Offset = SizeVal - BytesLeft;
180*9880d681SAndroid Build Coastguard Worker     EVT AddrVT = Dst.getValueType();
181*9880d681SAndroid Build Coastguard Worker     EVT SizeVT = Size.getValueType();
182*9880d681SAndroid Build Coastguard Worker 
183*9880d681SAndroid Build Coastguard Worker     Chain = DAG.getMemset(Chain, dl,
184*9880d681SAndroid Build Coastguard Worker                           DAG.getNode(ISD::ADD, dl, AddrVT, Dst,
185*9880d681SAndroid Build Coastguard Worker                                       DAG.getConstant(Offset, dl, AddrVT)),
186*9880d681SAndroid Build Coastguard Worker                           Src,
187*9880d681SAndroid Build Coastguard Worker                           DAG.getConstant(BytesLeft, dl, SizeVT),
188*9880d681SAndroid Build Coastguard Worker                           Align, isVolatile, false,
189*9880d681SAndroid Build Coastguard Worker                           DstPtrInfo.getWithOffset(Offset));
190*9880d681SAndroid Build Coastguard Worker   }
191*9880d681SAndroid Build Coastguard Worker 
192*9880d681SAndroid Build Coastguard Worker   // TODO: Use a Tokenfactor, as in memcpy, instead of a single chain.
193*9880d681SAndroid Build Coastguard Worker   return Chain;
194*9880d681SAndroid Build Coastguard Worker }
195*9880d681SAndroid Build Coastguard Worker 
EmitTargetCodeForMemcpy(SelectionDAG & DAG,const SDLoc & dl,SDValue Chain,SDValue Dst,SDValue Src,SDValue Size,unsigned Align,bool isVolatile,bool AlwaysInline,MachinePointerInfo DstPtrInfo,MachinePointerInfo SrcPtrInfo) const196*9880d681SAndroid Build Coastguard Worker SDValue X86SelectionDAGInfo::EmitTargetCodeForMemcpy(
197*9880d681SAndroid Build Coastguard Worker     SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src,
198*9880d681SAndroid Build Coastguard Worker     SDValue Size, unsigned Align, bool isVolatile, bool AlwaysInline,
199*9880d681SAndroid Build Coastguard Worker     MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const {
200*9880d681SAndroid Build Coastguard Worker   // This requires the copy size to be a constant, preferably
201*9880d681SAndroid Build Coastguard Worker   // within a subtarget-specific limit.
202*9880d681SAndroid Build Coastguard Worker   ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
203*9880d681SAndroid Build Coastguard Worker   const X86Subtarget &Subtarget =
204*9880d681SAndroid Build Coastguard Worker       DAG.getMachineFunction().getSubtarget<X86Subtarget>();
205*9880d681SAndroid Build Coastguard Worker   if (!ConstantSize)
206*9880d681SAndroid Build Coastguard Worker     return SDValue();
207*9880d681SAndroid Build Coastguard Worker   uint64_t SizeVal = ConstantSize->getZExtValue();
208*9880d681SAndroid Build Coastguard Worker   if (!AlwaysInline && SizeVal > Subtarget.getMaxInlineSizeThreshold())
209*9880d681SAndroid Build Coastguard Worker     return SDValue();
210*9880d681SAndroid Build Coastguard Worker 
211*9880d681SAndroid Build Coastguard Worker   /// If not DWORD aligned, it is more efficient to call the library.  However
212*9880d681SAndroid Build Coastguard Worker   /// if calling the library is not allowed (AlwaysInline), then soldier on as
213*9880d681SAndroid Build Coastguard Worker   /// the code generated here is better than the long load-store sequence we
214*9880d681SAndroid Build Coastguard Worker   /// would otherwise get.
215*9880d681SAndroid Build Coastguard Worker   if (!AlwaysInline && (Align & 3) != 0)
216*9880d681SAndroid Build Coastguard Worker     return SDValue();
217*9880d681SAndroid Build Coastguard Worker 
218*9880d681SAndroid Build Coastguard Worker   // If to a segment-relative address space, use the default lowering.
219*9880d681SAndroid Build Coastguard Worker   if (DstPtrInfo.getAddrSpace() >= 256 ||
220*9880d681SAndroid Build Coastguard Worker       SrcPtrInfo.getAddrSpace() >= 256)
221*9880d681SAndroid Build Coastguard Worker     return SDValue();
222*9880d681SAndroid Build Coastguard Worker 
223*9880d681SAndroid Build Coastguard Worker   // If the base register might conflict with our physical registers, bail out.
224*9880d681SAndroid Build Coastguard Worker   const MCPhysReg ClobberSet[] = {X86::RCX, X86::RSI, X86::RDI,
225*9880d681SAndroid Build Coastguard Worker                                   X86::ECX, X86::ESI, X86::EDI};
226*9880d681SAndroid Build Coastguard Worker   if (isBaseRegConflictPossible(DAG, ClobberSet))
227*9880d681SAndroid Build Coastguard Worker     return SDValue();
228*9880d681SAndroid Build Coastguard Worker 
229*9880d681SAndroid Build Coastguard Worker   MVT AVT;
230*9880d681SAndroid Build Coastguard Worker   if (Align & 1)
231*9880d681SAndroid Build Coastguard Worker     AVT = MVT::i8;
232*9880d681SAndroid Build Coastguard Worker   else if (Align & 2)
233*9880d681SAndroid Build Coastguard Worker     AVT = MVT::i16;
234*9880d681SAndroid Build Coastguard Worker   else if (Align & 4)
235*9880d681SAndroid Build Coastguard Worker     // DWORD aligned
236*9880d681SAndroid Build Coastguard Worker     AVT = MVT::i32;
237*9880d681SAndroid Build Coastguard Worker   else
238*9880d681SAndroid Build Coastguard Worker     // QWORD aligned
239*9880d681SAndroid Build Coastguard Worker     AVT = Subtarget.is64Bit() ? MVT::i64 : MVT::i32;
240*9880d681SAndroid Build Coastguard Worker 
241*9880d681SAndroid Build Coastguard Worker   unsigned UBytes = AVT.getSizeInBits() / 8;
242*9880d681SAndroid Build Coastguard Worker   unsigned CountVal = SizeVal / UBytes;
243*9880d681SAndroid Build Coastguard Worker   SDValue Count = DAG.getIntPtrConstant(CountVal, dl);
244*9880d681SAndroid Build Coastguard Worker   unsigned BytesLeft = SizeVal % UBytes;
245*9880d681SAndroid Build Coastguard Worker 
246*9880d681SAndroid Build Coastguard Worker   SDValue InFlag;
247*9880d681SAndroid Build Coastguard Worker   Chain = DAG.getCopyToReg(Chain, dl, Subtarget.is64Bit() ? X86::RCX : X86::ECX,
248*9880d681SAndroid Build Coastguard Worker                            Count, InFlag);
249*9880d681SAndroid Build Coastguard Worker   InFlag = Chain.getValue(1);
250*9880d681SAndroid Build Coastguard Worker   Chain = DAG.getCopyToReg(Chain, dl, Subtarget.is64Bit() ? X86::RDI : X86::EDI,
251*9880d681SAndroid Build Coastguard Worker                            Dst, InFlag);
252*9880d681SAndroid Build Coastguard Worker   InFlag = Chain.getValue(1);
253*9880d681SAndroid Build Coastguard Worker   Chain = DAG.getCopyToReg(Chain, dl, Subtarget.is64Bit() ? X86::RSI : X86::ESI,
254*9880d681SAndroid Build Coastguard Worker                            Src, InFlag);
255*9880d681SAndroid Build Coastguard Worker   InFlag = Chain.getValue(1);
256*9880d681SAndroid Build Coastguard Worker 
257*9880d681SAndroid Build Coastguard Worker   SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Glue);
258*9880d681SAndroid Build Coastguard Worker   SDValue Ops[] = { Chain, DAG.getValueType(AVT), InFlag };
259*9880d681SAndroid Build Coastguard Worker   SDValue RepMovs = DAG.getNode(X86ISD::REP_MOVS, dl, Tys, Ops);
260*9880d681SAndroid Build Coastguard Worker 
261*9880d681SAndroid Build Coastguard Worker   SmallVector<SDValue, 4> Results;
262*9880d681SAndroid Build Coastguard Worker   Results.push_back(RepMovs);
263*9880d681SAndroid Build Coastguard Worker   if (BytesLeft) {
264*9880d681SAndroid Build Coastguard Worker     // Handle the last 1 - 7 bytes.
265*9880d681SAndroid Build Coastguard Worker     unsigned Offset = SizeVal - BytesLeft;
266*9880d681SAndroid Build Coastguard Worker     EVT DstVT = Dst.getValueType();
267*9880d681SAndroid Build Coastguard Worker     EVT SrcVT = Src.getValueType();
268*9880d681SAndroid Build Coastguard Worker     EVT SizeVT = Size.getValueType();
269*9880d681SAndroid Build Coastguard Worker     Results.push_back(DAG.getMemcpy(Chain, dl,
270*9880d681SAndroid Build Coastguard Worker                                     DAG.getNode(ISD::ADD, dl, DstVT, Dst,
271*9880d681SAndroid Build Coastguard Worker                                                 DAG.getConstant(Offset, dl,
272*9880d681SAndroid Build Coastguard Worker                                                                 DstVT)),
273*9880d681SAndroid Build Coastguard Worker                                     DAG.getNode(ISD::ADD, dl, SrcVT, Src,
274*9880d681SAndroid Build Coastguard Worker                                                 DAG.getConstant(Offset, dl,
275*9880d681SAndroid Build Coastguard Worker                                                                 SrcVT)),
276*9880d681SAndroid Build Coastguard Worker                                     DAG.getConstant(BytesLeft, dl, SizeVT),
277*9880d681SAndroid Build Coastguard Worker                                     Align, isVolatile, AlwaysInline, false,
278*9880d681SAndroid Build Coastguard Worker                                     DstPtrInfo.getWithOffset(Offset),
279*9880d681SAndroid Build Coastguard Worker                                     SrcPtrInfo.getWithOffset(Offset)));
280*9880d681SAndroid Build Coastguard Worker   }
281*9880d681SAndroid Build Coastguard Worker 
282*9880d681SAndroid Build Coastguard Worker   return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Results);
283*9880d681SAndroid Build Coastguard Worker }
284