1 | //===-- X86SelectionDAGInfo.cpp - X86 SelectionDAG Info -------------------===//
|
---|
2 | //
|
---|
3 | // The LLVM Compiler Infrastructure
|
---|
4 | //
|
---|
5 | // This file is distributed under the University of Illinois Open Source
|
---|
6 | // License. See LICENSE.TXT for details.
|
---|
7 | //
|
---|
8 | //===----------------------------------------------------------------------===//
|
---|
9 | //
|
---|
10 | // This file implements the X86SelectionDAGInfo class.
|
---|
11 | //
|
---|
12 | //===----------------------------------------------------------------------===//
|
---|
13 |
|
---|
14 | #define DEBUG_TYPE "x86-selectiondag-info"
|
---|
15 | #include "X86TargetMachine.h"
|
---|
16 | #include "llvm/DerivedTypes.h"
|
---|
17 | #include "llvm/CodeGen/SelectionDAG.h"
|
---|
18 | using namespace llvm;
|
---|
19 |
|
---|
20 | X86SelectionDAGInfo::X86SelectionDAGInfo(const X86TargetMachine &TM) :
|
---|
21 | TargetSelectionDAGInfo(TM),
|
---|
22 | Subtarget(&TM.getSubtarget<X86Subtarget>()),
|
---|
23 | TLI(*TM.getTargetLowering()) {
|
---|
24 | }
|
---|
25 |
|
---|
26 | X86SelectionDAGInfo::~X86SelectionDAGInfo() {
|
---|
27 | }
|
---|
28 |
|
---|
29 | SDValue
|
---|
30 | X86SelectionDAGInfo::EmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl,
|
---|
31 | SDValue Chain,
|
---|
32 | SDValue Dst, SDValue Src,
|
---|
33 | SDValue Size, unsigned Align,
|
---|
34 | bool isVolatile,
|
---|
35 | const Value *DstSV,
|
---|
36 | uint64_t DstSVOff) const {
|
---|
37 | ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
|
---|
38 |
|
---|
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 ||
|
---|
43 | !ConstantSize ||
|
---|
44 | ConstantSize->getZExtValue() >
|
---|
45 | Subtarget->getMaxInlineSizeThreshold()) {
|
---|
46 | SDValue InFlag(0, 0);
|
---|
47 |
|
---|
48 | // Check to see if there is a specialized entry-point for memory zeroing.
|
---|
49 | ConstantSDNode *V = dyn_cast<ConstantSDNode>(Src);
|
---|
50 |
|
---|
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;
|
---|
57 | Entry.Node = Dst;
|
---|
58 | Entry.Ty = IntPtrTy;
|
---|
59 | Args.push_back(Entry);
|
---|
60 | Entry.Node = Size;
|
---|
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,
|
---|
67 | DAG, dl);
|
---|
68 | return CallResult.second;
|
---|
69 | }
|
---|
70 |
|
---|
71 | // Otherwise have the target-independent code call memset.
|
---|
72 | return SDValue();
|
---|
73 | }
|
---|
74 |
|
---|
75 | uint64_t SizeVal = ConstantSize->getZExtValue();
|
---|
76 | SDValue InFlag(0, 0);
|
---|
77 | EVT AVT;
|
---|
78 | SDValue Count;
|
---|
79 | ConstantSDNode *ValC = dyn_cast<ConstantSDNode>(Src);
|
---|
80 | unsigned BytesLeft = 0;
|
---|
81 | bool TwoRepStos = false;
|
---|
82 | if (ValC) {
|
---|
83 | unsigned ValReg;
|
---|
84 | uint64_t Val = ValC->getZExtValue() & 255;
|
---|
85 |
|
---|
86 | // If the value is a constant, then we can potentially use larger sets.
|
---|
87 | switch (Align & 3) {
|
---|
88 | case 2: // WORD aligned
|
---|
89 | AVT = MVT::i16;
|
---|
90 | ValReg = X86::AX;
|
---|
91 | Val = (Val << 8) | Val;
|
---|
92 | break;
|
---|
93 | case 0: // DWORD aligned
|
---|
94 | AVT = MVT::i32;
|
---|
95 | ValReg = X86::EAX;
|
---|
96 | Val = (Val << 8) | Val;
|
---|
97 | Val = (Val << 16) | Val;
|
---|
98 | if (Subtarget->is64Bit() && ((Align & 0x7) == 0)) { // QWORD aligned
|
---|
99 | AVT = MVT::i64;
|
---|
100 | ValReg = X86::RAX;
|
---|
101 | Val = (Val << 32) | Val;
|
---|
102 | }
|
---|
103 | break;
|
---|
104 | default: // Byte aligned
|
---|
105 | AVT = MVT::i8;
|
---|
106 | ValReg = X86::AL;
|
---|
107 | Count = DAG.getIntPtrConstant(SizeVal);
|
---|
108 | break;
|
---|
109 | }
|
---|
110 |
|
---|
111 | if (AVT.bitsGT(MVT::i8)) {
|
---|
112 | unsigned UBytes = AVT.getSizeInBits() / 8;
|
---|
113 | Count = DAG.getIntPtrConstant(SizeVal / UBytes);
|
---|
114 | BytesLeft = SizeVal % UBytes;
|
---|
115 | }
|
---|
116 |
|
---|
117 | Chain = DAG.getCopyToReg(Chain, dl, ValReg, DAG.getConstant(Val, AVT),
|
---|
118 | InFlag);
|
---|
119 | InFlag = Chain.getValue(1);
|
---|
120 | } else {
|
---|
121 | AVT = MVT::i8;
|
---|
122 | Count = DAG.getIntPtrConstant(SizeVal);
|
---|
123 | Chain = DAG.getCopyToReg(Chain, dl, X86::AL, Src, InFlag);
|
---|
124 | InFlag = Chain.getValue(1);
|
---|
125 | }
|
---|
126 |
|
---|
127 | Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RCX :
|
---|
128 | X86::ECX,
|
---|
129 | Count, InFlag);
|
---|
130 | InFlag = Chain.getValue(1);
|
---|
131 | Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RDI :
|
---|
132 | X86::EDI,
|
---|
133 | Dst, InFlag);
|
---|
134 | InFlag = Chain.getValue(1);
|
---|
135 |
|
---|
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));
|
---|
139 |
|
---|
140 | if (TwoRepStos) {
|
---|
141 | InFlag = Chain.getValue(1);
|
---|
142 | Count = Size;
|
---|
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 :
|
---|
147 | X86::ECX,
|
---|
148 | Left, InFlag);
|
---|
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();
|
---|
158 |
|
---|
159 | Chain = DAG.getMemset(Chain, dl,
|
---|
160 | DAG.getNode(ISD::ADD, dl, AddrVT, Dst,
|
---|
161 | DAG.getConstant(Offset, AddrVT)),
|
---|
162 | Src,
|
---|
163 | DAG.getConstant(BytesLeft, SizeVT),
|
---|
164 | Align, isVolatile, DstSV, DstSVOff + Offset);
|
---|
165 | }
|
---|
166 |
|
---|
167 | // TODO: Use a Tokenfactor, as in memcpy, instead of a single chain.
|
---|
168 | return Chain;
|
---|
169 | }
|
---|
170 |
|
---|
171 | SDValue
|
---|
172 | X86SelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl,
|
---|
173 | SDValue Chain, SDValue Dst, SDValue Src,
|
---|
174 | SDValue Size, unsigned Align,
|
---|
175 | bool isVolatile, bool AlwaysInline,
|
---|
176 | const Value *DstSV,
|
---|
177 | uint64_t DstSVOff,
|
---|
178 | const Value *SrcSV,
|
---|
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);
|
---|
183 | if (!ConstantSize)
|
---|
184 | return SDValue();
|
---|
185 | uint64_t SizeVal = ConstantSize->getZExtValue();
|
---|
186 | if (!AlwaysInline && SizeVal > Subtarget->getMaxInlineSizeThreshold())
|
---|
187 | return SDValue();
|
---|
188 |
|
---|
189 | /// If not DWORD aligned, call the library.
|
---|
190 | if ((Align & 3) != 0)
|
---|
191 | return SDValue();
|
---|
192 |
|
---|
193 | // DWORD aligned
|
---|
194 | EVT AVT = MVT::i32;
|
---|
195 | if (Subtarget->is64Bit() && ((Align & 0x7) == 0)) // QWORD aligned
|
---|
196 | AVT = MVT::i64;
|
---|
197 |
|
---|
198 | unsigned UBytes = AVT.getSizeInBits() / 8;
|
---|
199 | unsigned CountVal = SizeVal / UBytes;
|
---|
200 | SDValue Count = DAG.getIntPtrConstant(CountVal);
|
---|
201 | unsigned BytesLeft = SizeVal % UBytes;
|
---|
202 |
|
---|
203 | SDValue InFlag(0, 0);
|
---|
204 | Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RCX :
|
---|
205 | X86::ECX,
|
---|
206 | Count, InFlag);
|
---|
207 | InFlag = Chain.getValue(1);
|
---|
208 | Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RDI :
|
---|
209 | X86::EDI,
|
---|
210 | Dst, InFlag);
|
---|
211 | InFlag = Chain.getValue(1);
|
---|
212 | Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RSI :
|
---|
213 | X86::ESI,
|
---|
214 | Src, InFlag);
|
---|
215 | InFlag = Chain.getValue(1);
|
---|
216 |
|
---|
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));
|
---|
221 |
|
---|
222 | SmallVector<SDValue, 4> Results;
|
---|
223 | Results.push_back(RepMovs);
|
---|
224 | if (BytesLeft) {
|
---|
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));
|
---|
239 | }
|
---|
240 |
|
---|
241 | return DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
|
---|
242 | &Results[0], Results.size());
|
---|
243 | }
|
---|