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());