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,
35 MachinePointerInfo DstPtrInfo) const {
36 ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
38 // If not DWORD aligned or size is more than the threshold, call the library.
39 // The libc version is likely to be faster for these cases. It can use the
40 // address value and run time information about the CPU.
41 if ((Align & 3) != 0 ||
43 ConstantSize->getZExtValue() >
44 Subtarget->getMaxInlineSizeThreshold()) {
47 // Check to see if there is a specialized entry-point for memory zeroing.
48 ConstantSDNode *V = dyn_cast<ConstantSDNode>(Src);
50 if (const char *bzeroEntry = V &&
51 V->isNullValue() ? Subtarget->getBZeroEntry() : 0) {
52 EVT IntPtr = TLI.getPointerTy();
53 const Type *IntPtrTy = getTargetData()->getIntPtrType(*DAG.getContext());
54 TargetLowering::ArgListTy Args;
55 TargetLowering::ArgListEntry Entry;
58 Args.push_back(Entry);
60 Args.push_back(Entry);
61 std::pair<SDValue,SDValue> CallResult =
62 TLI.LowerCallTo(Chain, Type::getVoidTy(*DAG.getContext()),
63 false, false, false, false,
64 0, CallingConv::C, false, /*isReturnValueUsed=*/false,
65 DAG.getExternalSymbol(bzeroEntry, IntPtr), Args,
67 return CallResult.second;
70 // Otherwise have the target-independent code call memset.
74 uint64_t SizeVal = ConstantSize->getZExtValue();
78 ConstantSDNode *ValC = dyn_cast<ConstantSDNode>(Src);
79 unsigned BytesLeft = 0;
80 bool TwoRepStos = false;
83 uint64_t Val = ValC->getZExtValue() & 255;
85 // If the value is a constant, then we can potentially use larger sets.
87 case 2: // WORD aligned
90 Val = (Val << 8) | Val;
92 case 0: // DWORD aligned
95 Val = (Val << 8) | Val;
96 Val = (Val << 16) | Val;
97 if (Subtarget->is64Bit() && ((Align & 0x7) == 0)) { // QWORD aligned
100 Val = (Val << 32) | Val;
103 default: // Byte aligned
106 Count = DAG.getIntPtrConstant(SizeVal);
110 if (AVT.bitsGT(MVT::i8)) {
111 unsigned UBytes = AVT.getSizeInBits() / 8;
112 Count = DAG.getIntPtrConstant(SizeVal / UBytes);
113 BytesLeft = SizeVal % UBytes;
116 Chain = DAG.getCopyToReg(Chain, dl, ValReg, DAG.getConstant(Val, AVT),
118 InFlag = Chain.getValue(1);
121 Count = DAG.getIntPtrConstant(SizeVal);
122 Chain = DAG.getCopyToReg(Chain, dl, X86::AL, Src, InFlag);
123 InFlag = Chain.getValue(1);
126 Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RCX :
129 InFlag = Chain.getValue(1);
130 Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RDI :
133 InFlag = Chain.getValue(1);
135 SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
136 SDValue Ops[] = { Chain, DAG.getValueType(AVT), InFlag };
137 Chain = DAG.getNode(X86ISD::REP_STOS, dl, Tys, Ops, array_lengthof(Ops));
140 InFlag = Chain.getValue(1);
142 EVT CVT = Count.getValueType();
143 SDValue Left = DAG.getNode(ISD::AND, dl, CVT, Count,
144 DAG.getConstant((AVT == MVT::i64) ? 7 : 3, CVT));
145 Chain = DAG.getCopyToReg(Chain, dl, (CVT == MVT::i64) ? X86::RCX :
148 InFlag = Chain.getValue(1);
149 Tys = DAG.getVTList(MVT::Other, MVT::Flag);
150 SDValue Ops[] = { Chain, DAG.getValueType(MVT::i8), InFlag };
151 Chain = DAG.getNode(X86ISD::REP_STOS, dl, Tys, Ops, array_lengthof(Ops));
152 } else if (BytesLeft) {
153 // Handle the last 1 - 7 bytes.
154 unsigned Offset = SizeVal - BytesLeft;
155 EVT AddrVT = Dst.getValueType();
156 EVT SizeVT = Size.getValueType();
158 Chain = DAG.getMemset(Chain, dl,
159 DAG.getNode(ISD::ADD, dl, AddrVT, Dst,
160 DAG.getConstant(Offset, AddrVT)),
162 DAG.getConstant(BytesLeft, SizeVT),
163 Align, isVolatile, DstPtrInfo.getWithOffset(Offset));
166 // TODO: Use a Tokenfactor, as in memcpy, instead of a single chain.
171 X86SelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl,
172 SDValue Chain, SDValue Dst, SDValue Src,
173 SDValue Size, unsigned Align,
174 bool isVolatile, bool AlwaysInline,
175 MachinePointerInfo DstPtrInfo,
176 MachinePointerInfo SrcPtrInfo) const {
177 // This requires the copy size to be a constant, preferrably
178 // within a subtarget-specific limit.
179 ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
182 uint64_t SizeVal = ConstantSize->getZExtValue();
183 if (!AlwaysInline && SizeVal > Subtarget->getMaxInlineSizeThreshold())
186 /// If not DWORD aligned, call the library.
187 if ((Align & 3) != 0)
192 if (Subtarget->is64Bit() && ((Align & 0x7) == 0)) // QWORD aligned
195 unsigned UBytes = AVT.getSizeInBits() / 8;
196 unsigned CountVal = SizeVal / UBytes;
197 SDValue Count = DAG.getIntPtrConstant(CountVal);
198 unsigned BytesLeft = SizeVal % UBytes;
200 SDValue InFlag(0, 0);
201 Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RCX :
204 InFlag = Chain.getValue(1);
205 Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RDI :
208 InFlag = Chain.getValue(1);
209 Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RSI :
212 InFlag = Chain.getValue(1);
214 SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
215 SDValue Ops[] = { Chain, DAG.getValueType(AVT), InFlag };
216 SDValue RepMovs = DAG.getNode(X86ISD::REP_MOVS, dl, Tys, Ops,
217 array_lengthof(Ops));
219 SmallVector<SDValue, 4> Results;
220 Results.push_back(RepMovs);
222 // Handle the last 1 - 7 bytes.
223 unsigned Offset = SizeVal - BytesLeft;
224 EVT DstVT = Dst.getValueType();
225 EVT SrcVT = Src.getValueType();
226 EVT SizeVT = Size.getValueType();
227 Results.push_back(DAG.getMemcpy(Chain, dl,
228 DAG.getNode(ISD::ADD, dl, DstVT, Dst,
229 DAG.getConstant(Offset, DstVT)),
230 DAG.getNode(ISD::ADD, dl, SrcVT, Src,
231 DAG.getConstant(Offset, SrcVT)),
232 DAG.getConstant(BytesLeft, SizeVT),
233 Align, isVolatile, AlwaysInline,
234 DstPtrInfo.getWithOffset(Offset),
235 SrcPtrInfo.getWithOffset(Offset)));
238 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
239 &Results[0], Results.size());