LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
X86SelectionDAGInfo.cpp
Go to the documentation of this file.
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"
17 #include "llvm/IR/DerivedTypes.h"
18 using namespace llvm;
19 
22  Subtarget(&TM.getSubtarget<X86Subtarget>()),
23  TLI(*TM.getTargetLowering()) {
24 }
25 
27 }
28 
29 SDValue
31  SDValue Chain,
32  SDValue Dst, SDValue Src,
33  SDValue Size, unsigned Align,
34  bool isVolatile,
35  MachinePointerInfo DstPtrInfo) const {
36  ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
37 
38  // If to a segment-relative address space, use the default lowering.
39  if (DstPtrInfo.getAddrSpace() >= 256)
40  return SDValue();
41 
42  // If not DWORD aligned or size is more than the threshold, call the library.
43  // The libc version is likely to be faster for these cases. It can use the
44  // address value and run time information about the CPU.
45  if ((Align & 3) != 0 ||
46  !ConstantSize ||
47  ConstantSize->getZExtValue() >
48  Subtarget->getMaxInlineSizeThreshold()) {
49  // Check to see if there is a specialized entry-point for memory zeroing.
51 
52  if (const char *bzeroEntry = V &&
53  V->isNullValue() ? Subtarget->getBZeroEntry() : 0) {
54  EVT IntPtr = TLI.getPointerTy();
55  Type *IntPtrTy = getDataLayout()->getIntPtrType(*DAG.getContext());
58  Entry.Node = Dst;
59  Entry.Ty = IntPtrTy;
60  Args.push_back(Entry);
61  Entry.Node = Size;
62  Args.push_back(Entry);
65  false, false, false, false,
66  0, CallingConv::C, /*isTailCall=*/false,
67  /*doesNotRet=*/false, /*isReturnValueUsed=*/false,
68  DAG.getExternalSymbol(bzeroEntry, IntPtr), Args,
69  DAG, dl);
70  std::pair<SDValue,SDValue> CallResult =
71  TLI.LowerCallTo(CLI);
72  return CallResult.second;
73  }
74 
75  // Otherwise have the target-independent code call memset.
76  return SDValue();
77  }
78 
79  uint64_t SizeVal = ConstantSize->getZExtValue();
80  SDValue InFlag(0, 0);
81  EVT AVT;
82  SDValue Count;
84  unsigned BytesLeft = 0;
85  bool TwoRepStos = false;
86  if (ValC) {
87  unsigned ValReg;
88  uint64_t Val = ValC->getZExtValue() & 255;
89 
90  // If the value is a constant, then we can potentially use larger sets.
91  switch (Align & 3) {
92  case 2: // WORD aligned
93  AVT = MVT::i16;
94  ValReg = X86::AX;
95  Val = (Val << 8) | Val;
96  break;
97  case 0: // DWORD aligned
98  AVT = MVT::i32;
99  ValReg = X86::EAX;
100  Val = (Val << 8) | Val;
101  Val = (Val << 16) | Val;
102  if (Subtarget->is64Bit() && ((Align & 0x7) == 0)) { // QWORD aligned
103  AVT = MVT::i64;
104  ValReg = X86::RAX;
105  Val = (Val << 32) | Val;
106  }
107  break;
108  default: // Byte aligned
109  AVT = MVT::i8;
110  ValReg = X86::AL;
111  Count = DAG.getIntPtrConstant(SizeVal);
112  break;
113  }
114 
115  if (AVT.bitsGT(MVT::i8)) {
116  unsigned UBytes = AVT.getSizeInBits() / 8;
117  Count = DAG.getIntPtrConstant(SizeVal / UBytes);
118  BytesLeft = SizeVal % UBytes;
119  }
120 
121  Chain = DAG.getCopyToReg(Chain, dl, ValReg, DAG.getConstant(Val, AVT),
122  InFlag);
123  InFlag = Chain.getValue(1);
124  } else {
125  AVT = MVT::i8;
126  Count = DAG.getIntPtrConstant(SizeVal);
127  Chain = DAG.getCopyToReg(Chain, dl, X86::AL, Src, InFlag);
128  InFlag = Chain.getValue(1);
129  }
130 
131  Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RCX :
132  X86::ECX,
133  Count, InFlag);
134  InFlag = Chain.getValue(1);
135  Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RDI :
136  X86::EDI,
137  Dst, InFlag);
138  InFlag = Chain.getValue(1);
139 
141  SDValue Ops[] = { Chain, DAG.getValueType(AVT), InFlag };
142  Chain = DAG.getNode(X86ISD::REP_STOS, dl, Tys, Ops, array_lengthof(Ops));
143 
144  if (TwoRepStos) {
145  InFlag = Chain.getValue(1);
146  Count = Size;
147  EVT CVT = Count.getValueType();
148  SDValue Left = DAG.getNode(ISD::AND, dl, CVT, Count,
149  DAG.getConstant((AVT == MVT::i64) ? 7 : 3, CVT));
150  Chain = DAG.getCopyToReg(Chain, dl, (CVT == MVT::i64) ? X86::RCX :
151  X86::ECX,
152  Left, InFlag);
153  InFlag = Chain.getValue(1);
154  Tys = DAG.getVTList(MVT::Other, MVT::Glue);
155  SDValue Ops[] = { Chain, DAG.getValueType(MVT::i8), InFlag };
156  Chain = DAG.getNode(X86ISD::REP_STOS, dl, Tys, Ops, array_lengthof(Ops));
157  } else if (BytesLeft) {
158  // Handle the last 1 - 7 bytes.
159  unsigned Offset = SizeVal - BytesLeft;
160  EVT AddrVT = Dst.getValueType();
161  EVT SizeVT = Size.getValueType();
162 
163  Chain = DAG.getMemset(Chain, dl,
164  DAG.getNode(ISD::ADD, dl, AddrVT, Dst,
165  DAG.getConstant(Offset, AddrVT)),
166  Src,
167  DAG.getConstant(BytesLeft, SizeVT),
168  Align, isVolatile, DstPtrInfo.getWithOffset(Offset));
169  }
170 
171  // TODO: Use a Tokenfactor, as in memcpy, instead of a single chain.
172  return Chain;
173 }
174 
175 SDValue
177  SDValue Chain, SDValue Dst, SDValue Src,
178  SDValue Size, unsigned Align,
179  bool isVolatile, bool AlwaysInline,
180  MachinePointerInfo DstPtrInfo,
181  MachinePointerInfo SrcPtrInfo) const {
182  // This requires the copy size to be a constant, preferably
183  // within a subtarget-specific limit.
184  ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
185  if (!ConstantSize)
186  return SDValue();
187  uint64_t SizeVal = ConstantSize->getZExtValue();
188  if (!AlwaysInline && SizeVal > Subtarget->getMaxInlineSizeThreshold())
189  return SDValue();
190 
191  /// If not DWORD aligned, it is more efficient to call the library. However
192  /// if calling the library is not allowed (AlwaysInline), then soldier on as
193  /// the code generated here is better than the long load-store sequence we
194  /// would otherwise get.
195  if (!AlwaysInline && (Align & 3) != 0)
196  return SDValue();
197 
198  // If to a segment-relative address space, use the default lowering.
199  if (DstPtrInfo.getAddrSpace() >= 256 ||
200  SrcPtrInfo.getAddrSpace() >= 256)
201  return SDValue();
202 
203  // ESI might be used as a base pointer, in that case we can't simply overwrite
204  // the register. Fall back to generic code.
205  const X86RegisterInfo *TRI =
206  static_cast<const X86RegisterInfo *>(DAG.getTarget().getRegisterInfo());
207  if (TRI->hasBasePointer(DAG.getMachineFunction()) &&
208  TRI->getBaseRegister() == X86::ESI)
209  return SDValue();
210 
211  MVT AVT;
212  if (Align & 1)
213  AVT = MVT::i8;
214  else if (Align & 2)
215  AVT = MVT::i16;
216  else if (Align & 4)
217  // DWORD aligned
218  AVT = MVT::i32;
219  else
220  // QWORD aligned
221  AVT = Subtarget->is64Bit() ? MVT::i64 : MVT::i32;
222 
223  unsigned UBytes = AVT.getSizeInBits() / 8;
224  unsigned CountVal = SizeVal / UBytes;
225  SDValue Count = DAG.getIntPtrConstant(CountVal);
226  unsigned BytesLeft = SizeVal % UBytes;
227 
228  SDValue InFlag(0, 0);
229  Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RCX :
230  X86::ECX,
231  Count, InFlag);
232  InFlag = Chain.getValue(1);
233  Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RDI :
234  X86::EDI,
235  Dst, InFlag);
236  InFlag = Chain.getValue(1);
237  Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RSI :
238  X86::ESI,
239  Src, InFlag);
240  InFlag = Chain.getValue(1);
241 
243  SDValue Ops[] = { Chain, DAG.getValueType(AVT), InFlag };
244  SDValue RepMovs = DAG.getNode(X86ISD::REP_MOVS, dl, Tys, Ops,
245  array_lengthof(Ops));
246 
247  SmallVector<SDValue, 4> Results;
248  Results.push_back(RepMovs);
249  if (BytesLeft) {
250  // Handle the last 1 - 7 bytes.
251  unsigned Offset = SizeVal - BytesLeft;
252  EVT DstVT = Dst.getValueType();
253  EVT SrcVT = Src.getValueType();
254  EVT SizeVT = Size.getValueType();
255  Results.push_back(DAG.getMemcpy(Chain, dl,
256  DAG.getNode(ISD::ADD, dl, DstVT, Dst,
257  DAG.getConstant(Offset, DstVT)),
258  DAG.getNode(ISD::ADD, dl, SrcVT, Src,
259  DAG.getConstant(Offset, SrcVT)),
260  DAG.getConstant(BytesLeft, SizeVT),
261  Align, isVolatile, AlwaysInline,
262  DstPtrInfo.getWithOffset(Offset),
263  SrcPtrInfo.getWithOffset(Offset)));
264  }
265 
266  return DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
267  &Results[0], Results.size());
268 }
unsigned getMaxInlineSizeThreshold() const
Definition: X86Subtarget.h:223
SDValue getConstant(uint64_t Val, EVT VT, bool isTarget=false)
SDValue getValue(unsigned R) const
LLVMContext * getContext() const
Definition: SelectionDAG.h:285
SDValue getCopyToReg(SDValue Chain, SDLoc dl, unsigned Reg, SDValue N)
Definition: SelectionDAG.h:487
bool hasBasePointer(const MachineFunction &MF) const
enable_if_c<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:266
const TargetMachine & getTarget() const
Definition: SelectionDAG.h:281
unsigned getSizeInBits() const
Definition: ValueTypes.h:359
X86SelectionDAGInfo(const X86TargetMachine &TM)
SDValue getExternalSymbol(const char *Sym, EVT VT)
MachineFunction & getMachineFunction() const
Definition: SelectionDAG.h:280
MachinePointerInfo getWithOffset(int64_t O) const
SDVTList getVTList(EVT VT)
virtual MVT getPointerTy(uint32_t=0) const
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
size_t array_lengthof(T(&)[N])
Find the length of an array.
Definition: STLExtras.h:250
const DataLayout * getDataLayout() const
bool is64Bit() const
Is this x86_64? (disregarding specific ABI / programming model)
Definition: X86Subtarget.h:240
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:176
REP_STOS - Repeat fill, corresponds to X86::REP_STOSx.
static Type * getVoidTy(LLVMContext &C)
Definition: Type.cpp:227
REP_MOVS - Repeat move, corresponds to X86::REP_MOVSx.
std::vector< ArgListEntry > ArgListTy
unsigned getBaseRegister() const
SDValue getMemcpy(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool isVol, bool AlwaysInline, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo)
bool bitsGT(EVT VT) const
bitsGT - Return true if this has more bits than VT.
Definition: ValueTypes.h:723
IntegerType * getIntPtrType(LLVMContext &C, unsigned AddressSpace=0) const
Definition: DataLayout.cpp:610
SDValue getIntPtrConstant(uint64_t Val, bool isTarget=false)
virtual SDValue EmitTargetCodeForMemcpy(SelectionDAG &DAG, SDLoc dl, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool isVolatile, bool AlwaysInline, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const
unsigned getAddrSpace() const
SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT)
static cl::opt< AlignMode > Align(cl::desc("Load/store alignment support"), cl::Hidden, cl::init(DefaultAlign), cl::values(clEnumValN(DefaultAlign,"arm-default-align","Generate unaligned accesses only on hardware/OS ""combinations that are known to support them"), clEnumValN(StrictAlign,"arm-strict-align","Disallow all unaligned memory accesses"), clEnumValN(NoStrictAlign,"arm-no-strict-align","Allow unaligned memory accesses"), clEnumValEnd))
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:295
unsigned getSizeInBits() const
getSizeInBits - Return the size of the specified value type in bits.
Definition: ValueTypes.h:779
virtual const TargetRegisterInfo * getRegisterInfo() const
SDValue getMemset(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool isVol, MachinePointerInfo DstPtrInfo)
EVT getValueType() const
SDValue getValueType(EVT)
const char * getBZeroEntry() const
virtual SDValue EmitTargetCodeForMemset(SelectionDAG &DAG, SDLoc dl, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool isVolatile, MachinePointerInfo DstPtrInfo) const
uint64_t getZExtValue() const