1 //===-- X86SelectionDAGInfo.cpp - X86 SelectionDAG Info -------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the X86SelectionDAGInfo class.
12 //===----------------------------------------------------------------------===//
14 #define DEBUG_TYPE "x86-selectiondag-info"
15 #include "X86TargetMachine.h"
16 #include "llvm/DerivedTypes.h"
17 #include "llvm/CodeGen/SelectionDAG.h"
20 X86SelectionDAGInfo::X86SelectionDAGInfo(const X86TargetMachine &TM) :
21 TargetSelectionDAGInfo(TM),
22 Subtarget(&TM.getSubtarget<X86Subtarget>()),
23 TLI(*TM.getTargetLowering()) {
26 X86SelectionDAGInfo::~X86SelectionDAGInfo() {
30 X86SelectionDAGInfo::EmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl,
32 SDValue Dst, SDValue Src,
33 SDValue Size, unsigned Align,
36 uint64_t DstSVOff) const {
37 ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
39 // If not DWORD aligned or size is more than the threshold, call the library.
40 // The libc version is likely to be faster for these cases. It can use the
41 // address value and run time information about the CPU.
42 if ((Align & 3) != 0 ||
44 ConstantSize->getZExtValue() >
45 Subtarget->getMaxInlineSizeThreshold()) {
48 // Check to see if there is a specialized entry-point for memory zeroing.
49 ConstantSDNode *V = dyn_cast<ConstantSDNode>(Src);
51 if (const char *bzeroEntry = V &&
52 V->isNullValue() ? Subtarget->getBZeroEntry() : 0) {
53 EVT IntPtr = TLI.getPointerTy();
54 const Type *IntPtrTy = getTargetData()->getIntPtrType(*DAG.getContext());
55 TargetLowering::ArgListTy Args;
56 TargetLowering::ArgListEntry Entry;
59 Args.push_back(Entry);
61 Args.push_back(Entry);
62 std::pair<SDValue,SDValue> CallResult =
63 TLI.LowerCallTo(Chain, Type::getVoidTy(*DAG.getContext()),
64 false, false, false, false,
65 0, CallingConv::C, false, /*isReturnValueUsed=*/false,
66 DAG.getExternalSymbol(bzeroEntry, IntPtr), Args,
68 return CallResult.second;
71 // Otherwise have the target-independent code call memset.
75 uint64_t SizeVal = ConstantSize->getZExtValue();
79 ConstantSDNode *ValC = dyn_cast<ConstantSDNode>(Src);
80 unsigned BytesLeft = 0;
81 bool TwoRepStos = false;
84 uint64_t Val = ValC->getZExtValue() & 255;
86 // If the value is a constant, then we can potentially use larger sets.
88 case 2: // WORD aligned
91 Val = (Val << 8) | Val;
93 case 0: // DWORD aligned
96 Val = (Val << 8) | Val;
97 Val = (Val << 16) | Val;
98 if (Subtarget->is64Bit() && ((Align & 0x7) == 0)) { // QWORD aligned
101 Val = (Val << 32) | Val;
104 default: // Byte aligned
107 Count = DAG.getIntPtrConstant(SizeVal);
111 if (AVT.bitsGT(MVT::i8)) {
112 unsigned UBytes = AVT.getSizeInBits() / 8;
113 Count = DAG.getIntPtrConstant(SizeVal / UBytes);
114 BytesLeft = SizeVal % UBytes;
117 Chain = DAG.getCopyToReg(Chain, dl, ValReg, DAG.getConstant(Val, AVT),
119 InFlag = Chain.getValue(1);
122 Count = DAG.getIntPtrConstant(SizeVal);
123 Chain = DAG.getCopyToReg(Chain, dl, X86::AL, Src, InFlag);
124 InFlag = Chain.getValue(1);
127 Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RCX :
130 InFlag = Chain.getValue(1);
131 Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RDI :
134 InFlag = Chain.getValue(1);
136 SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
137 SDValue Ops[] = { Chain, DAG.getValueType(AVT), InFlag };
138 Chain = DAG.getNode(X86ISD::REP_STOS, dl, Tys, Ops, array_lengthof(Ops));
141 InFlag = Chain.getValue(1);
143 EVT CVT = Count.getValueType();
144 SDValue Left = DAG.getNode(ISD::AND, dl, CVT, Count,
145 DAG.getConstant((AVT == MVT::i64) ? 7 : 3, CVT));
146 Chain = DAG.getCopyToReg(Chain, dl, (CVT == MVT::i64) ? X86::RCX :
149 InFlag = Chain.getValue(1);
150 Tys = DAG.getVTList(MVT::Other, MVT::Flag);
151 SDValue Ops[] = { Chain, DAG.getValueType(MVT::i8), InFlag };
152 Chain = DAG.getNode(X86ISD::REP_STOS, dl, Tys, Ops, array_lengthof(Ops));
153 } else if (BytesLeft) {
154 // Handle the last 1 - 7 bytes.
155 unsigned Offset = SizeVal - BytesLeft;
156 EVT AddrVT = Dst.getValueType();
157 EVT SizeVT = Size.getValueType();
159 Chain = DAG.getMemset(Chain, dl,
160 DAG.getNode(ISD::ADD, dl, AddrVT, Dst,
161 DAG.getConstant(Offset, AddrVT)),
163 DAG.getConstant(BytesLeft, SizeVT),
164 Align, isVolatile, DstSV, DstSVOff + Offset);
167 // TODO: Use a Tokenfactor, as in memcpy, instead of a single chain.
172 X86SelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl,
173 SDValue Chain, SDValue Dst, SDValue Src,
174 SDValue Size, unsigned Align,
175 bool isVolatile, bool AlwaysInline,
179 uint64_t SrcSVOff) const {
180 // This requires the copy size to be a constant, preferrably
181 // within a subtarget-specific limit.
182 ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
185 uint64_t SizeVal = ConstantSize->getZExtValue();
186 if (!AlwaysInline && SizeVal > Subtarget->getMaxInlineSizeThreshold())
189 /// If not DWORD aligned, call the library.
190 if ((Align & 3) != 0)
195 if (Subtarget->is64Bit() && ((Align & 0x7) == 0)) // QWORD aligned
198 unsigned UBytes = AVT.getSizeInBits() / 8;
199 unsigned CountVal = SizeVal / UBytes;
200 SDValue Count = DAG.getIntPtrConstant(CountVal);
201 unsigned BytesLeft = SizeVal % UBytes;
203 SDValue InFlag(0, 0);
204 Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RCX :
207 InFlag = Chain.getValue(1);
208 Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RDI :
211 InFlag = Chain.getValue(1);
212 Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RSI :
215 InFlag = Chain.getValue(1);
217 SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
218 SDValue Ops[] = { Chain, DAG.getValueType(AVT), InFlag };
219 SDValue RepMovs = DAG.getNode(X86ISD::REP_MOVS, dl, Tys, Ops,
220 array_lengthof(Ops));
222 SmallVector<SDValue, 4> Results;
223 Results.push_back(RepMovs);
225 // Handle the last 1 - 7 bytes.
226 unsigned Offset = SizeVal - BytesLeft;
227 EVT DstVT = Dst.getValueType();
228 EVT SrcVT = Src.getValueType();
229 EVT SizeVT = Size.getValueType();
230 Results.push_back(DAG.getMemcpy(Chain, dl,
231 DAG.getNode(ISD::ADD, dl, DstVT, Dst,
232 DAG.getConstant(Offset, DstVT)),
233 DAG.getNode(ISD::ADD, dl, SrcVT, Src,
234 DAG.getConstant(Offset, SrcVT)),
235 DAG.getConstant(BytesLeft, SizeVT),
236 Align, isVolatile, AlwaysInline,
237 DstSV, DstSVOff + Offset,
238 SrcSV, SrcSVOff + Offset));
241 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
242 &Results[0], Results.size());