X86SelectionDAGInfo.cpp revision 1e92ec688624d17b552c88afc956f61da4948cbb
153c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman//===-- X86SelectionDAGInfo.cpp - X86 SelectionDAG Info -------------------===//
253c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman//
353c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman//                     The LLVM Compiler Infrastructure
453c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman//
553c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman// This file is distributed under the University of Illinois Open Source
653c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman// License. See LICENSE.TXT for details.
753c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman//
853c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman//===----------------------------------------------------------------------===//
953c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman//
1053c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman// This file implements the X86SelectionDAGInfo class.
1153c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman//
1253c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman//===----------------------------------------------------------------------===//
1353c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman
1453c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman#define DEBUG_TYPE "x86-selectiondag-info"
15ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman#include "X86TargetMachine.h"
16ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman#include "llvm/DerivedTypes.h"
17ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman#include "llvm/CodeGen/SelectionDAG.h"
1853c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohmanusing namespace llvm;
1953c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman
20ff7a562751604a9fe13efc75bd59622244b54d35Dan GohmanX86SelectionDAGInfo::X86SelectionDAGInfo(const X86TargetMachine &TM) :
21ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  TargetSelectionDAGInfo(TM),
22ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  Subtarget(&TM.getSubtarget<X86Subtarget>()),
23ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  TLI(*TM.getTargetLowering()) {
2453c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman}
2553c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman
2653c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan GohmanX86SelectionDAGInfo::~X86SelectionDAGInfo() {
2753c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman}
28ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
29ff7a562751604a9fe13efc75bd59622244b54d35Dan GohmanSDValue
30ff7a562751604a9fe13efc75bd59622244b54d35Dan GohmanX86SelectionDAGInfo::EmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl,
31ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                             SDValue Chain,
32ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                             SDValue Dst, SDValue Src,
33ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                             SDValue Size, unsigned Align,
34ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                             bool isVolatile,
35e72f2027e9116c55a5b39ac72732df8d6c45d37cChris Lattner                                         MachinePointerInfo DstPtrInfo) const {
36ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
37ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
38e54b482d1c6ec714a73d8a87a4f7583aa86fac9fChris Lattner  // If to a segment-relative address space, use the default lowering.
39e54b482d1c6ec714a73d8a87a4f7583aa86fac9fChris Lattner  if (DstPtrInfo.getAddrSpace() >= 256)
40e54b482d1c6ec714a73d8a87a4f7583aa86fac9fChris Lattner    return SDValue();
41e54b482d1c6ec714a73d8a87a4f7583aa86fac9fChris Lattner
42ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  // If not DWORD aligned or size is more than the threshold, call the library.
43ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  // The libc version is likely to be faster for these cases. It can use the
44ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  // address value and run time information about the CPU.
45ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  if ((Align & 3) != 0 ||
46ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      !ConstantSize ||
47ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      ConstantSize->getZExtValue() >
48ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman        Subtarget->getMaxInlineSizeThreshold()) {
49ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    SDValue InFlag(0, 0);
50ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
51ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    // Check to see if there is a specialized entry-point for memory zeroing.
52ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    ConstantSDNode *V = dyn_cast<ConstantSDNode>(Src);
53ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
54ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    if (const char *bzeroEntry =  V &&
55ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman        V->isNullValue() ? Subtarget->getBZeroEntry() : 0) {
56ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      EVT IntPtr = TLI.getPointerTy();
57ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      const Type *IntPtrTy = getTargetData()->getIntPtrType(*DAG.getContext());
58ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      TargetLowering::ArgListTy Args;
59ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      TargetLowering::ArgListEntry Entry;
60ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      Entry.Node = Dst;
61ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      Entry.Ty = IntPtrTy;
62ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      Args.push_back(Entry);
63ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      Entry.Node = Size;
64ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      Args.push_back(Entry);
65ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      std::pair<SDValue,SDValue> CallResult =
66ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman        TLI.LowerCallTo(Chain, Type::getVoidTy(*DAG.getContext()),
67ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                        false, false, false, false,
68ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                        0, CallingConv::C, false, /*isReturnValueUsed=*/false,
69ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                        DAG.getExternalSymbol(bzeroEntry, IntPtr), Args,
70ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                        DAG, dl);
71ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      return CallResult.second;
72ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    }
73ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
74ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    // Otherwise have the target-independent code call memset.
75ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    return SDValue();
76ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  }
77ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
78ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  uint64_t SizeVal = ConstantSize->getZExtValue();
79ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  SDValue InFlag(0, 0);
80ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  EVT AVT;
81ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  SDValue Count;
82ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  ConstantSDNode *ValC = dyn_cast<ConstantSDNode>(Src);
83ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  unsigned BytesLeft = 0;
84ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  bool TwoRepStos = false;
85ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  if (ValC) {
86ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    unsigned ValReg;
87ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    uint64_t Val = ValC->getZExtValue() & 255;
88ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
89ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    // If the value is a constant, then we can potentially use larger sets.
90ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    switch (Align & 3) {
91ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    case 2:   // WORD aligned
92ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      AVT = MVT::i16;
93ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      ValReg = X86::AX;
94ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      Val = (Val << 8) | Val;
95ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      break;
96ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    case 0:  // DWORD aligned
97ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      AVT = MVT::i32;
98ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      ValReg = X86::EAX;
99ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      Val = (Val << 8)  | Val;
100ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      Val = (Val << 16) | Val;
101ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      if (Subtarget->is64Bit() && ((Align & 0x7) == 0)) {  // QWORD aligned
102ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman        AVT = MVT::i64;
103ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman        ValReg = X86::RAX;
104ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman        Val = (Val << 32) | Val;
105ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      }
106ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      break;
107ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    default:  // Byte aligned
108ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      AVT = MVT::i8;
109ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      ValReg = X86::AL;
110ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      Count = DAG.getIntPtrConstant(SizeVal);
111ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      break;
112ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    }
113ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
114ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    if (AVT.bitsGT(MVT::i8)) {
115ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      unsigned UBytes = AVT.getSizeInBits() / 8;
116ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      Count = DAG.getIntPtrConstant(SizeVal / UBytes);
117ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      BytesLeft = SizeVal % UBytes;
118ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    }
119ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
120ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    Chain  = DAG.getCopyToReg(Chain, dl, ValReg, DAG.getConstant(Val, AVT),
121ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                              InFlag);
122ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    InFlag = Chain.getValue(1);
123ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  } else {
124ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    AVT = MVT::i8;
125ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    Count  = DAG.getIntPtrConstant(SizeVal);
126ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    Chain  = DAG.getCopyToReg(Chain, dl, X86::AL, Src, InFlag);
127ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    InFlag = Chain.getValue(1);
128ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  }
129ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
130ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  Chain  = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RCX :
131ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                                              X86::ECX,
132ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                            Count, InFlag);
133ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  InFlag = Chain.getValue(1);
134ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  Chain  = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RDI :
135ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                                              X86::EDI,
136ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                            Dst, InFlag);
137ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  InFlag = Chain.getValue(1);
138ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
139ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
140ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  SDValue Ops[] = { Chain, DAG.getValueType(AVT), InFlag };
141ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  Chain = DAG.getNode(X86ISD::REP_STOS, dl, Tys, Ops, array_lengthof(Ops));
142ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
143ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  if (TwoRepStos) {
144ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    InFlag = Chain.getValue(1);
145ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    Count  = Size;
146ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    EVT CVT = Count.getValueType();
147ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    SDValue Left = DAG.getNode(ISD::AND, dl, CVT, Count,
148ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                               DAG.getConstant((AVT == MVT::i64) ? 7 : 3, CVT));
149ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    Chain  = DAG.getCopyToReg(Chain, dl, (CVT == MVT::i64) ? X86::RCX :
150ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                                             X86::ECX,
151ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                              Left, InFlag);
152ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    InFlag = Chain.getValue(1);
153ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    Tys = DAG.getVTList(MVT::Other, MVT::Flag);
154ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    SDValue Ops[] = { Chain, DAG.getValueType(MVT::i8), InFlag };
155ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    Chain = DAG.getNode(X86ISD::REP_STOS, dl, Tys, Ops, array_lengthof(Ops));
156ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  } else if (BytesLeft) {
157ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    // Handle the last 1 - 7 bytes.
158ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    unsigned Offset = SizeVal - BytesLeft;
159ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    EVT AddrVT = Dst.getValueType();
160ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    EVT SizeVT = Size.getValueType();
161ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
162ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    Chain = DAG.getMemset(Chain, dl,
163ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                          DAG.getNode(ISD::ADD, dl, AddrVT, Dst,
164ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                      DAG.getConstant(Offset, AddrVT)),
165ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                          Src,
166ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                          DAG.getConstant(BytesLeft, SizeVT),
167e72f2027e9116c55a5b39ac72732df8d6c45d37cChris Lattner                          Align, isVolatile, DstPtrInfo.getWithOffset(Offset));
168ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  }
169ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
170ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  // TODO: Use a Tokenfactor, as in memcpy, instead of a single chain.
171ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  return Chain;
172ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman}
173ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
174ff7a562751604a9fe13efc75bd59622244b54d35Dan GohmanSDValue
175ff7a562751604a9fe13efc75bd59622244b54d35Dan GohmanX86SelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl,
176ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                        SDValue Chain, SDValue Dst, SDValue Src,
177ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                        SDValue Size, unsigned Align,
178ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                        bool isVolatile, bool AlwaysInline,
179e72f2027e9116c55a5b39ac72732df8d6c45d37cChris Lattner                                         MachinePointerInfo DstPtrInfo,
180e72f2027e9116c55a5b39ac72732df8d6c45d37cChris Lattner                                         MachinePointerInfo SrcPtrInfo) const {
181ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  // This requires the copy size to be a constant, preferrably
182ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  // within a subtarget-specific limit.
183ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
184ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  if (!ConstantSize)
185ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    return SDValue();
186ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  uint64_t SizeVal = ConstantSize->getZExtValue();
187ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  if (!AlwaysInline && SizeVal > Subtarget->getMaxInlineSizeThreshold())
188ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    return SDValue();
189ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
1901e92ec688624d17b552c88afc956f61da4948cbbDuncan Sands  /// If not DWORD aligned, it is more efficient to call the library.  However
1911e92ec688624d17b552c88afc956f61da4948cbbDuncan Sands  /// if calling the library is not allowed (AlwaysInline), then soldier on as
1921e92ec688624d17b552c88afc956f61da4948cbbDuncan Sands  /// the code generated here is better than the long load-store sequence we
1931e92ec688624d17b552c88afc956f61da4948cbbDuncan Sands  /// would otherwise get.
1941e92ec688624d17b552c88afc956f61da4948cbbDuncan Sands  if (!AlwaysInline && (Align & 3) != 0)
195ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    return SDValue();
196ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
197e54b482d1c6ec714a73d8a87a4f7583aa86fac9fChris Lattner  // If to a segment-relative address space, use the default lowering.
198e54b482d1c6ec714a73d8a87a4f7583aa86fac9fChris Lattner  if (DstPtrInfo.getAddrSpace() >= 256 ||
199e54b482d1c6ec714a73d8a87a4f7583aa86fac9fChris Lattner      SrcPtrInfo.getAddrSpace() >= 256)
200e54b482d1c6ec714a73d8a87a4f7583aa86fac9fChris Lattner    return SDValue();
2011e92ec688624d17b552c88afc956f61da4948cbbDuncan Sands
2021e92ec688624d17b552c88afc956f61da4948cbbDuncan Sands  MVT AVT;
2031e92ec688624d17b552c88afc956f61da4948cbbDuncan Sands  if (Align & 1)
2041e92ec688624d17b552c88afc956f61da4948cbbDuncan Sands    AVT = MVT::i8;
2051e92ec688624d17b552c88afc956f61da4948cbbDuncan Sands  else if (Align & 2)
2061e92ec688624d17b552c88afc956f61da4948cbbDuncan Sands    AVT = MVT::i16;
2071e92ec688624d17b552c88afc956f61da4948cbbDuncan Sands  else if (Align & 4)
2081e92ec688624d17b552c88afc956f61da4948cbbDuncan Sands    // DWORD aligned
2091e92ec688624d17b552c88afc956f61da4948cbbDuncan Sands    AVT = MVT::i32;
2101e92ec688624d17b552c88afc956f61da4948cbbDuncan Sands  else
2111e92ec688624d17b552c88afc956f61da4948cbbDuncan Sands    // QWORD aligned
2121e92ec688624d17b552c88afc956f61da4948cbbDuncan Sands    AVT = Subtarget->is64Bit() ? MVT::i64 : MVT::i32;
213ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
214ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  unsigned UBytes = AVT.getSizeInBits() / 8;
215ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  unsigned CountVal = SizeVal / UBytes;
216ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  SDValue Count = DAG.getIntPtrConstant(CountVal);
217ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  unsigned BytesLeft = SizeVal % UBytes;
218ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
219ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  SDValue InFlag(0, 0);
220ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  Chain  = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RCX :
221ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                                              X86::ECX,
222ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                            Count, InFlag);
223ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  InFlag = Chain.getValue(1);
224ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  Chain  = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RDI :
225ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                                              X86::EDI,
226ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                            Dst, InFlag);
227ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  InFlag = Chain.getValue(1);
228ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  Chain  = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RSI :
229ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                                              X86::ESI,
230ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                            Src, InFlag);
231ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  InFlag = Chain.getValue(1);
232ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
233ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
234ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  SDValue Ops[] = { Chain, DAG.getValueType(AVT), InFlag };
235ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  SDValue RepMovs = DAG.getNode(X86ISD::REP_MOVS, dl, Tys, Ops,
236ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                array_lengthof(Ops));
237ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
238ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  SmallVector<SDValue, 4> Results;
239ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  Results.push_back(RepMovs);
240ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  if (BytesLeft) {
241ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    // Handle the last 1 - 7 bytes.
242ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    unsigned Offset = SizeVal - BytesLeft;
243ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    EVT DstVT = Dst.getValueType();
244ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    EVT SrcVT = Src.getValueType();
245ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    EVT SizeVT = Size.getValueType();
246ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    Results.push_back(DAG.getMemcpy(Chain, dl,
247ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                    DAG.getNode(ISD::ADD, dl, DstVT, Dst,
248ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                                DAG.getConstant(Offset, DstVT)),
249ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                    DAG.getNode(ISD::ADD, dl, SrcVT, Src,
250ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                                DAG.getConstant(Offset, SrcVT)),
251ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                    DAG.getConstant(BytesLeft, SizeVT),
252ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                    Align, isVolatile, AlwaysInline,
253e72f2027e9116c55a5b39ac72732df8d6c45d37cChris Lattner                                    DstPtrInfo.getWithOffset(Offset),
254e72f2027e9116c55a5b39ac72732df8d6c45d37cChris Lattner                                    SrcPtrInfo.getWithOffset(Offset)));
255ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  }
256ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
257ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  return DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
258ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                     &Results[0], Results.size());
259ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman}
260