source: clamav/trunk/libclamav/c++/llvm/lib/Target/X86/X86SelectionDAGInfo.cpp@ 319

Last change on this file since 319 was 319, checked in by Yuri Dario, 14 years ago

clamav: update trunk to 0.97.

File size: 9.3 KB
Line 
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"
18using namespace llvm;
19
20X86SelectionDAGInfo::X86SelectionDAGInfo(const X86TargetMachine &TM) :
21 TargetSelectionDAGInfo(TM),
22 Subtarget(&TM.getSubtarget<X86Subtarget>()),
23 TLI(*TM.getTargetLowering()) {
24}
25
26X86SelectionDAGInfo::~X86SelectionDAGInfo() {
27}
28
29SDValue
30X86SelectionDAGInfo::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
171SDValue
172X86SelectionDAGInfo::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}
Note: See TracBrowser for help on using the repository browser.