xref: /freebsd/contrib/llvm-project/llvm/lib/Target/X86/X86SelectionDAGInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- X86SelectionDAGInfo.cpp - X86 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 X86SelectionDAGInfo class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "X86SelectionDAGInfo.h"
140b57cec5SDimitry Andric #include "X86ISelLowering.h"
150b57cec5SDimitry Andric #include "X86InstrInfo.h"
160b57cec5SDimitry Andric #include "X86RegisterInfo.h"
170b57cec5SDimitry Andric #include "X86Subtarget.h"
185ffd83dbSDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAG.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLowering.h"
210b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric using namespace llvm;
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric #define DEBUG_TYPE "x86-selectiondag-info"
260b57cec5SDimitry Andric 
27e8d8bef9SDimitry Andric static cl::opt<bool>
28e8d8bef9SDimitry Andric     UseFSRMForMemcpy("x86-use-fsrm-for-memcpy", cl::Hidden, cl::init(false),
29e8d8bef9SDimitry Andric                      cl::desc("Use fast short rep mov in memcpy lowering"));
30e8d8bef9SDimitry Andric 
isBaseRegConflictPossible(SelectionDAG & DAG,ArrayRef<MCPhysReg> ClobberSet) const310b57cec5SDimitry Andric bool X86SelectionDAGInfo::isBaseRegConflictPossible(
320b57cec5SDimitry Andric     SelectionDAG &DAG, ArrayRef<MCPhysReg> ClobberSet) const {
330b57cec5SDimitry Andric   // We cannot use TRI->hasBasePointer() until *after* we select all basic
340b57cec5SDimitry Andric   // blocks.  Legalization may introduce new stack temporaries with large
350b57cec5SDimitry Andric   // alignment requirements.  Fall back to generic code if there are any
360b57cec5SDimitry Andric   // dynamic stack adjustments (hopefully rare) and the base pointer would
370b57cec5SDimitry Andric   // conflict if we had to use it.
380b57cec5SDimitry Andric   MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
390b57cec5SDimitry Andric   if (!MFI.hasVarSizedObjects() && !MFI.hasOpaqueSPAdjustment())
400b57cec5SDimitry Andric     return false;
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric   const X86RegisterInfo *TRI = static_cast<const X86RegisterInfo *>(
430b57cec5SDimitry Andric       DAG.getSubtarget().getRegisterInfo());
44fe6060f1SDimitry Andric   return llvm::is_contained(ClobberSet, TRI->getBaseRegister());
450b57cec5SDimitry Andric }
460b57cec5SDimitry Andric 
EmitTargetCodeForMemset(SelectionDAG & DAG,const SDLoc & dl,SDValue Chain,SDValue Dst,SDValue Val,SDValue Size,Align Alignment,bool isVolatile,bool AlwaysInline,MachinePointerInfo DstPtrInfo) const470b57cec5SDimitry Andric SDValue X86SelectionDAGInfo::EmitTargetCodeForMemset(
480b57cec5SDimitry Andric     SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Val,
4981ad6265SDimitry Andric     SDValue Size, Align Alignment, bool isVolatile, bool AlwaysInline,
500b57cec5SDimitry Andric     MachinePointerInfo DstPtrInfo) const {
510b57cec5SDimitry Andric   // If to a segment-relative address space, use the default lowering.
520b57cec5SDimitry Andric   if (DstPtrInfo.getAddrSpace() >= 256)
530b57cec5SDimitry Andric     return SDValue();
540b57cec5SDimitry Andric 
55*0fca6ea1SDimitry Andric   // If the base register might conflict with our physical registers, bail out.
56*0fca6ea1SDimitry Andric   const MCPhysReg ClobberSet[] = {X86::RCX, X86::RAX, X86::RDI,
57*0fca6ea1SDimitry Andric                                   X86::ECX, X86::EAX, X86::EDI};
58*0fca6ea1SDimitry Andric   if (isBaseRegConflictPossible(DAG, ClobberSet))
59*0fca6ea1SDimitry Andric     return SDValue();
60*0fca6ea1SDimitry Andric 
61*0fca6ea1SDimitry Andric   ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
62*0fca6ea1SDimitry Andric   const X86Subtarget &Subtarget =
63*0fca6ea1SDimitry Andric       DAG.getMachineFunction().getSubtarget<X86Subtarget>();
64*0fca6ea1SDimitry Andric 
650b57cec5SDimitry Andric   // If not DWORD aligned or size is more than the threshold, call the library.
660b57cec5SDimitry Andric   // The libc version is likely to be faster for these cases. It can use the
670b57cec5SDimitry Andric   // address value and run time information about the CPU.
685ffd83dbSDimitry Andric   if (Alignment < Align(4) || !ConstantSize ||
6981ad6265SDimitry Andric       ConstantSize->getZExtValue() > Subtarget.getMaxInlineSizeThreshold())
700b57cec5SDimitry Andric     return SDValue();
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   uint64_t SizeVal = ConstantSize->getZExtValue();
7306c3fb27SDimitry Andric   SDValue InGlue;
740b57cec5SDimitry Andric   EVT AVT;
750b57cec5SDimitry Andric   SDValue Count;
760b57cec5SDimitry Andric   unsigned BytesLeft = 0;
77bdd1243dSDimitry Andric   if (auto *ValC = dyn_cast<ConstantSDNode>(Val)) {
780b57cec5SDimitry Andric     unsigned ValReg;
790b57cec5SDimitry Andric     uint64_t Val = ValC->getZExtValue() & 255;
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric     // If the value is a constant, then we can potentially use larger sets.
82*0fca6ea1SDimitry Andric     if (Alignment >= Align(4)) {
835ffd83dbSDimitry Andric       // DWORD aligned
840b57cec5SDimitry Andric       AVT = MVT::i32;
850b57cec5SDimitry Andric       ValReg = X86::EAX;
860b57cec5SDimitry Andric       Val = (Val << 8)  | Val;
870b57cec5SDimitry Andric       Val = (Val << 16) | Val;
88*0fca6ea1SDimitry Andric       if (Subtarget.is64Bit() && Alignment >= Align(8)) { // QWORD aligned
890b57cec5SDimitry Andric         AVT = MVT::i64;
900b57cec5SDimitry Andric         ValReg = X86::RAX;
910b57cec5SDimitry Andric         Val = (Val << 32) | Val;
920b57cec5SDimitry Andric       }
935ffd83dbSDimitry Andric     } else if (Alignment == Align(2)) {
945ffd83dbSDimitry Andric       // WORD aligned
955ffd83dbSDimitry Andric       AVT = MVT::i16;
965ffd83dbSDimitry Andric       ValReg = X86::AX;
975ffd83dbSDimitry Andric       Val = (Val << 8) | Val;
985ffd83dbSDimitry Andric     } else {
995ffd83dbSDimitry Andric       // Byte aligned
1000b57cec5SDimitry Andric       AVT = MVT::i8;
1010b57cec5SDimitry Andric       ValReg = X86::AL;
1020b57cec5SDimitry Andric       Count = DAG.getIntPtrConstant(SizeVal, dl);
1030b57cec5SDimitry Andric     }
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric     if (AVT.bitsGT(MVT::i8)) {
1060b57cec5SDimitry Andric       unsigned UBytes = AVT.getSizeInBits() / 8;
1070b57cec5SDimitry Andric       Count = DAG.getIntPtrConstant(SizeVal / UBytes, dl);
1080b57cec5SDimitry Andric       BytesLeft = SizeVal % UBytes;
1090b57cec5SDimitry Andric     }
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric     Chain = DAG.getCopyToReg(Chain, dl, ValReg, DAG.getConstant(Val, dl, AVT),
11206c3fb27SDimitry Andric                              InGlue);
11306c3fb27SDimitry Andric     InGlue = Chain.getValue(1);
1140b57cec5SDimitry Andric   } else {
1150b57cec5SDimitry Andric     AVT = MVT::i8;
1160b57cec5SDimitry Andric     Count  = DAG.getIntPtrConstant(SizeVal, dl);
11706c3fb27SDimitry Andric     Chain  = DAG.getCopyToReg(Chain, dl, X86::AL, Val, InGlue);
11806c3fb27SDimitry Andric     InGlue = Chain.getValue(1);
1190b57cec5SDimitry Andric   }
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   bool Use64BitRegs = Subtarget.isTarget64BitLP64();
1220b57cec5SDimitry Andric   Chain = DAG.getCopyToReg(Chain, dl, Use64BitRegs ? X86::RCX : X86::ECX,
12306c3fb27SDimitry Andric                            Count, InGlue);
12406c3fb27SDimitry Andric   InGlue = Chain.getValue(1);
1250b57cec5SDimitry Andric   Chain = DAG.getCopyToReg(Chain, dl, Use64BitRegs ? X86::RDI : X86::EDI,
12606c3fb27SDimitry Andric                            Dst, InGlue);
12706c3fb27SDimitry Andric   InGlue = Chain.getValue(1);
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Glue);
13006c3fb27SDimitry Andric   SDValue Ops[] = {Chain, DAG.getValueType(AVT), InGlue};
131*0fca6ea1SDimitry Andric   SDValue RepStos = DAG.getNode(X86ISD::REP_STOS, dl, Tys, Ops);
1320b57cec5SDimitry Andric 
133*0fca6ea1SDimitry Andric   /// RepStos can process the whole length.
134*0fca6ea1SDimitry Andric   if (BytesLeft == 0)
135*0fca6ea1SDimitry Andric     return RepStos;
136*0fca6ea1SDimitry Andric 
1370b57cec5SDimitry Andric   // Handle the last 1 - 7 bytes.
138*0fca6ea1SDimitry Andric   SmallVector<SDValue, 4> Results;
139*0fca6ea1SDimitry Andric   Results.push_back(RepStos);
1400b57cec5SDimitry Andric   unsigned Offset = SizeVal - BytesLeft;
1410b57cec5SDimitry Andric   EVT AddrVT = Dst.getValueType();
1420b57cec5SDimitry Andric   EVT SizeVT = Size.getValueType();
1430b57cec5SDimitry Andric 
144*0fca6ea1SDimitry Andric   Results.push_back(
1455ffd83dbSDimitry Andric       DAG.getMemset(Chain, dl,
1460b57cec5SDimitry Andric                     DAG.getNode(ISD::ADD, dl, AddrVT, Dst,
1470b57cec5SDimitry Andric                                 DAG.getConstant(Offset, dl, AddrVT)),
1485ffd83dbSDimitry Andric                     Val, DAG.getConstant(BytesLeft, dl, SizeVT), Alignment,
14981ad6265SDimitry Andric                     isVolatile, AlwaysInline,
150*0fca6ea1SDimitry Andric                     /* CI */ nullptr, DstPtrInfo.getWithOffset(Offset)));
1510b57cec5SDimitry Andric 
152*0fca6ea1SDimitry Andric   return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Results);
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric /// Emit a single REP MOVS{B,W,D,Q} instruction.
emitRepmovs(const X86Subtarget & Subtarget,SelectionDAG & DAG,const SDLoc & dl,SDValue Chain,SDValue Dst,SDValue Src,SDValue Size,MVT AVT)1560b57cec5SDimitry Andric static SDValue emitRepmovs(const X86Subtarget &Subtarget, SelectionDAG &DAG,
1570b57cec5SDimitry Andric                            const SDLoc &dl, SDValue Chain, SDValue Dst,
1580b57cec5SDimitry Andric                            SDValue Src, SDValue Size, MVT AVT) {
1590b57cec5SDimitry Andric   const bool Use64BitRegs = Subtarget.isTarget64BitLP64();
1600b57cec5SDimitry Andric   const unsigned CX = Use64BitRegs ? X86::RCX : X86::ECX;
1610b57cec5SDimitry Andric   const unsigned DI = Use64BitRegs ? X86::RDI : X86::EDI;
1620b57cec5SDimitry Andric   const unsigned SI = Use64BitRegs ? X86::RSI : X86::ESI;
1630b57cec5SDimitry Andric 
16406c3fb27SDimitry Andric   SDValue InGlue;
16506c3fb27SDimitry Andric   Chain = DAG.getCopyToReg(Chain, dl, CX, Size, InGlue);
16606c3fb27SDimitry Andric   InGlue = Chain.getValue(1);
16706c3fb27SDimitry Andric   Chain = DAG.getCopyToReg(Chain, dl, DI, Dst, InGlue);
16806c3fb27SDimitry Andric   InGlue = Chain.getValue(1);
16906c3fb27SDimitry Andric   Chain = DAG.getCopyToReg(Chain, dl, SI, Src, InGlue);
17006c3fb27SDimitry Andric   InGlue = Chain.getValue(1);
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Glue);
17306c3fb27SDimitry Andric   SDValue Ops[] = {Chain, DAG.getValueType(AVT), InGlue};
1740b57cec5SDimitry Andric   return DAG.getNode(X86ISD::REP_MOVS, dl, Tys, Ops);
1750b57cec5SDimitry Andric }
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric /// Emit a single REP MOVSB instruction for a particular constant size.
emitRepmovsB(const X86Subtarget & Subtarget,SelectionDAG & DAG,const SDLoc & dl,SDValue Chain,SDValue Dst,SDValue Src,uint64_t Size)1780b57cec5SDimitry Andric static SDValue emitRepmovsB(const X86Subtarget &Subtarget, SelectionDAG &DAG,
1790b57cec5SDimitry Andric                             const SDLoc &dl, SDValue Chain, SDValue Dst,
1800b57cec5SDimitry Andric                             SDValue Src, uint64_t Size) {
1810b57cec5SDimitry Andric   return emitRepmovs(Subtarget, DAG, dl, Chain, Dst, Src,
1820b57cec5SDimitry Andric                      DAG.getIntPtrConstant(Size, dl), MVT::i8);
1830b57cec5SDimitry Andric }
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric /// Returns the best type to use with repmovs depending on alignment.
getOptimalRepmovsType(const X86Subtarget & Subtarget,Align Alignment)1860b57cec5SDimitry Andric static MVT getOptimalRepmovsType(const X86Subtarget &Subtarget,
18706c3fb27SDimitry Andric                                  Align Alignment) {
18806c3fb27SDimitry Andric   uint64_t Align = Alignment.value();
1890b57cec5SDimitry Andric   assert((Align != 0) && "Align is normalized");
1900b57cec5SDimitry Andric   assert(isPowerOf2_64(Align) && "Align is a power of 2");
1910b57cec5SDimitry Andric   switch (Align) {
1920b57cec5SDimitry Andric   case 1:
1930b57cec5SDimitry Andric     return MVT::i8;
1940b57cec5SDimitry Andric   case 2:
1950b57cec5SDimitry Andric     return MVT::i16;
1960b57cec5SDimitry Andric   case 4:
1970b57cec5SDimitry Andric     return MVT::i32;
1980b57cec5SDimitry Andric   default:
1990b57cec5SDimitry Andric     return Subtarget.is64Bit() ? MVT::i64 : MVT::i32;
2000b57cec5SDimitry Andric   }
2010b57cec5SDimitry Andric }
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric /// Returns a REP MOVS instruction, possibly with a few load/stores to implement
2040b57cec5SDimitry Andric /// a constant size memory copy. In some cases where we know REP MOVS is
2050b57cec5SDimitry Andric /// inefficient we return an empty SDValue so the calling code can either
2060b57cec5SDimitry Andric /// generate a load/store sequence or call the runtime memcpy function.
emitConstantSizeRepmov(SelectionDAG & DAG,const X86Subtarget & Subtarget,const SDLoc & dl,SDValue Chain,SDValue Dst,SDValue Src,uint64_t Size,EVT SizeVT,Align Alignment,bool isVolatile,bool AlwaysInline,MachinePointerInfo DstPtrInfo,MachinePointerInfo SrcPtrInfo)2070b57cec5SDimitry Andric static SDValue emitConstantSizeRepmov(
2080b57cec5SDimitry Andric     SelectionDAG &DAG, const X86Subtarget &Subtarget, const SDLoc &dl,
2090b57cec5SDimitry Andric     SDValue Chain, SDValue Dst, SDValue Src, uint64_t Size, EVT SizeVT,
21006c3fb27SDimitry Andric     Align Alignment, bool isVolatile, bool AlwaysInline,
2110b57cec5SDimitry Andric     MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) {
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   /// TODO: Revisit next line: big copy with ERMSB on march >= haswell are very
2140b57cec5SDimitry Andric   /// efficient.
2150b57cec5SDimitry Andric   if (!AlwaysInline && Size > Subtarget.getMaxInlineSizeThreshold())
2160b57cec5SDimitry Andric     return SDValue();
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric   /// If we have enhanced repmovs we use it.
2190b57cec5SDimitry Andric   if (Subtarget.hasERMSB())
2200b57cec5SDimitry Andric     return emitRepmovsB(Subtarget, DAG, dl, Chain, Dst, Src, Size);
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric   assert(!Subtarget.hasERMSB() && "No efficient RepMovs");
2230b57cec5SDimitry Andric   /// We assume runtime memcpy will do a better job for unaligned copies when
2240b57cec5SDimitry Andric   /// ERMS is not present.
22506c3fb27SDimitry Andric   if (!AlwaysInline && (Alignment.value() & 3) != 0)
2260b57cec5SDimitry Andric     return SDValue();
2270b57cec5SDimitry Andric 
22806c3fb27SDimitry Andric   const MVT BlockType = getOptimalRepmovsType(Subtarget, Alignment);
2290b57cec5SDimitry Andric   const uint64_t BlockBytes = BlockType.getSizeInBits() / 8;
2300b57cec5SDimitry Andric   const uint64_t BlockCount = Size / BlockBytes;
2310b57cec5SDimitry Andric   const uint64_t BytesLeft = Size % BlockBytes;
2320b57cec5SDimitry Andric   SDValue RepMovs =
2330b57cec5SDimitry Andric       emitRepmovs(Subtarget, DAG, dl, Chain, Dst, Src,
2340b57cec5SDimitry Andric                   DAG.getIntPtrConstant(BlockCount, dl), BlockType);
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric   /// RepMov can process the whole length.
2370b57cec5SDimitry Andric   if (BytesLeft == 0)
2380b57cec5SDimitry Andric     return RepMovs;
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric   assert(BytesLeft && "We have leftover at this point");
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric   /// In case we optimize for size we use repmovsb even if it's less efficient
2430b57cec5SDimitry Andric   /// so we can save the loads/stores of the leftover.
2440b57cec5SDimitry Andric   if (DAG.getMachineFunction().getFunction().hasMinSize())
2450b57cec5SDimitry Andric     return emitRepmovsB(Subtarget, DAG, dl, Chain, Dst, Src, Size);
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric   // Handle the last 1 - 7 bytes.
2480b57cec5SDimitry Andric   SmallVector<SDValue, 4> Results;
2490b57cec5SDimitry Andric   Results.push_back(RepMovs);
2500b57cec5SDimitry Andric   unsigned Offset = Size - BytesLeft;
2510b57cec5SDimitry Andric   EVT DstVT = Dst.getValueType();
2520b57cec5SDimitry Andric   EVT SrcVT = Src.getValueType();
2530b57cec5SDimitry Andric   Results.push_back(DAG.getMemcpy(
2540b57cec5SDimitry Andric       Chain, dl,
2550b57cec5SDimitry Andric       DAG.getNode(ISD::ADD, dl, DstVT, Dst, DAG.getConstant(Offset, dl, DstVT)),
2560b57cec5SDimitry Andric       DAG.getNode(ISD::ADD, dl, SrcVT, Src, DAG.getConstant(Offset, dl, SrcVT)),
25706c3fb27SDimitry Andric       DAG.getConstant(BytesLeft, dl, SizeVT), Alignment, isVolatile,
258*0fca6ea1SDimitry Andric       /*AlwaysInline*/ true, /*CI=*/nullptr, std::nullopt,
2590b57cec5SDimitry Andric       DstPtrInfo.getWithOffset(Offset), SrcPtrInfo.getWithOffset(Offset)));
2600b57cec5SDimitry Andric   return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Results);
2610b57cec5SDimitry Andric }
2620b57cec5SDimitry 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) const2630b57cec5SDimitry Andric SDValue X86SelectionDAGInfo::EmitTargetCodeForMemcpy(
2640b57cec5SDimitry Andric     SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src,
2655ffd83dbSDimitry Andric     SDValue Size, Align Alignment, bool isVolatile, bool AlwaysInline,
2660b57cec5SDimitry Andric     MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const {
2670b57cec5SDimitry Andric   // If to a segment-relative address space, use the default lowering.
2680b57cec5SDimitry Andric   if (DstPtrInfo.getAddrSpace() >= 256 || SrcPtrInfo.getAddrSpace() >= 256)
2690b57cec5SDimitry Andric     return SDValue();
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric   // If the base registers conflict with our physical registers, use the default
2720b57cec5SDimitry Andric   // lowering.
2730b57cec5SDimitry Andric   const MCPhysReg ClobberSet[] = {X86::RCX, X86::RSI, X86::RDI,
2740b57cec5SDimitry Andric                                   X86::ECX, X86::ESI, X86::EDI};
2750b57cec5SDimitry Andric   if (isBaseRegConflictPossible(DAG, ClobberSet))
2760b57cec5SDimitry Andric     return SDValue();
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric   const X86Subtarget &Subtarget =
2790b57cec5SDimitry Andric       DAG.getMachineFunction().getSubtarget<X86Subtarget>();
2800b57cec5SDimitry Andric 
281e8d8bef9SDimitry Andric   // If enabled and available, use fast short rep mov.
282e8d8bef9SDimitry Andric   if (UseFSRMForMemcpy && Subtarget.hasFSRM())
283e8d8bef9SDimitry Andric     return emitRepmovs(Subtarget, DAG, dl, Chain, Dst, Src, Size, MVT::i8);
284e8d8bef9SDimitry Andric 
2850b57cec5SDimitry Andric   /// Handle constant sizes,
2860b57cec5SDimitry Andric   if (ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size))
28706c3fb27SDimitry Andric     return emitConstantSizeRepmov(DAG, Subtarget, dl, Chain, Dst, Src,
28806c3fb27SDimitry Andric                                   ConstantSize->getZExtValue(),
28906c3fb27SDimitry Andric                                   Size.getValueType(), Alignment, isVolatile,
29006c3fb27SDimitry Andric                                   AlwaysInline, DstPtrInfo, SrcPtrInfo);
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric   return SDValue();
2930b57cec5SDimitry Andric }
294