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