LLVM  3.7.0
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 #include "X86InstrInfo.h"
15 #include "X86ISelLowering.h"
16 #include "X86RegisterInfo.h"
17 #include "X86Subtarget.h"
18 #include "X86SelectionDAGInfo.h"
20 #include "llvm/IR/DerivedTypes.h"
22 
23 using namespace llvm;
24 
25 #define DEBUG_TYPE "x86-selectiondag-info"
26 
27 bool X86SelectionDAGInfo::isBaseRegConflictPossible(
28  SelectionDAG &DAG, ArrayRef<unsigned> ClobberSet) const {
29  // We cannot use TRI->hasBasePointer() until *after* we select all basic
30  // blocks. Legalization may introduce new stack temporaries with large
31  // alignment requirements. Fall back to generic code if there are any
32  // dynamic stack adjustments (hopefully rare) and the base pointer would
33  // conflict if we had to use it.
35  if (!MFI->hasVarSizedObjects() && !MFI->hasOpaqueSPAdjustment())
36  return false;
37 
38  const X86RegisterInfo *TRI = static_cast<const X86RegisterInfo *>(
40  unsigned BaseReg = TRI->getBaseRegister();
41  for (unsigned R : ClobberSet)
42  if (BaseReg == R)
43  return true;
44  return false;
45 }
46 
47 SDValue
49  SDValue Chain,
50  SDValue Dst, SDValue Src,
51  SDValue Size, unsigned Align,
52  bool isVolatile,
53  MachinePointerInfo DstPtrInfo) const {
54  ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
55  const X86Subtarget &Subtarget =
57 
58 #ifndef NDEBUG
59  // If the base register might conflict with our physical registers, bail out.
60  const unsigned ClobberSet[] = {X86::RCX, X86::RAX, X86::RDI,
61  X86::ECX, X86::EAX, X86::EDI};
62  assert(!isBaseRegConflictPossible(DAG, ClobberSet));
63 #endif
64 
65  // If to a segment-relative address space, use the default lowering.
66  if (DstPtrInfo.getAddrSpace() >= 256)
67  return SDValue();
68 
69  // If not DWORD aligned or size is more than the threshold, call the library.
70  // The libc version is likely to be faster for these cases. It can use the
71  // address value and run time information about the CPU.
72  if ((Align & 3) != 0 || !ConstantSize ||
73  ConstantSize->getZExtValue() > Subtarget.getMaxInlineSizeThreshold()) {
74  // Check to see if there is a specialized entry-point for memory zeroing.
76 
77  if (const char *bzeroEntry = V &&
78  V->isNullValue() ? Subtarget.getBZeroEntry() : nullptr) {
79  EVT IntPtr =
81  Type *IntPtrTy = DAG.getDataLayout().getIntPtrType(*DAG.getContext());
84  Entry.Node = Dst;
85  Entry.Ty = IntPtrTy;
86  Args.push_back(Entry);
87  Entry.Node = Size;
88  Args.push_back(Entry);
89 
91  CLI.setDebugLoc(dl).setChain(Chain)
93  DAG.getExternalSymbol(bzeroEntry, IntPtr), std::move(Args),
94  0)
95  .setDiscardResult();
96 
97  std::pair<SDValue,SDValue> CallResult = DAG.getTargetLoweringInfo().LowerCallTo(CLI);
98  return CallResult.second;
99  }
100 
101  // Otherwise have the target-independent code call memset.
102  return SDValue();
103  }
104 
105  uint64_t SizeVal = ConstantSize->getZExtValue();
106  SDValue InFlag;
107  EVT AVT;
108  SDValue Count;
109  ConstantSDNode *ValC = dyn_cast<ConstantSDNode>(Src);
110  unsigned BytesLeft = 0;
111  bool TwoRepStos = false;
112  if (ValC) {
113  unsigned ValReg;
114  uint64_t Val = ValC->getZExtValue() & 255;
115 
116  // If the value is a constant, then we can potentially use larger sets.
117  switch (Align & 3) {
118  case 2: // WORD aligned
119  AVT = MVT::i16;
120  ValReg = X86::AX;
121  Val = (Val << 8) | Val;
122  break;
123  case 0: // DWORD aligned
124  AVT = MVT::i32;
125  ValReg = X86::EAX;
126  Val = (Val << 8) | Val;
127  Val = (Val << 16) | Val;
128  if (Subtarget.is64Bit() && ((Align & 0x7) == 0)) { // QWORD aligned
129  AVT = MVT::i64;
130  ValReg = X86::RAX;
131  Val = (Val << 32) | Val;
132  }
133  break;
134  default: // Byte aligned
135  AVT = MVT::i8;
136  ValReg = X86::AL;
137  Count = DAG.getIntPtrConstant(SizeVal, dl);
138  break;
139  }
140 
141  if (AVT.bitsGT(MVT::i8)) {
142  unsigned UBytes = AVT.getSizeInBits() / 8;
143  Count = DAG.getIntPtrConstant(SizeVal / UBytes, dl);
144  BytesLeft = SizeVal % UBytes;
145  }
146 
147  Chain = DAG.getCopyToReg(Chain, dl, ValReg, DAG.getConstant(Val, dl, AVT),
148  InFlag);
149  InFlag = Chain.getValue(1);
150  } else {
151  AVT = MVT::i8;
152  Count = DAG.getIntPtrConstant(SizeVal, dl);
153  Chain = DAG.getCopyToReg(Chain, dl, X86::AL, Src, InFlag);
154  InFlag = Chain.getValue(1);
155  }
156 
157  Chain = DAG.getCopyToReg(Chain, dl, Subtarget.is64Bit() ? X86::RCX : X86::ECX,
158  Count, InFlag);
159  InFlag = Chain.getValue(1);
160  Chain = DAG.getCopyToReg(Chain, dl, Subtarget.is64Bit() ? X86::RDI : X86::EDI,
161  Dst, InFlag);
162  InFlag = Chain.getValue(1);
163 
165  SDValue Ops[] = { Chain, DAG.getValueType(AVT), InFlag };
166  Chain = DAG.getNode(X86ISD::REP_STOS, dl, Tys, Ops);
167 
168  if (TwoRepStos) {
169  InFlag = Chain.getValue(1);
170  Count = Size;
171  EVT CVT = Count.getValueType();
172  SDValue Left = DAG.getNode(ISD::AND, dl, CVT, Count,
173  DAG.getConstant((AVT == MVT::i64) ? 7 : 3, dl,
174  CVT));
175  Chain = DAG.getCopyToReg(Chain, dl, (CVT == MVT::i64) ? X86::RCX :
176  X86::ECX,
177  Left, InFlag);
178  InFlag = Chain.getValue(1);
179  Tys = DAG.getVTList(MVT::Other, MVT::Glue);
180  SDValue Ops[] = { Chain, DAG.getValueType(MVT::i8), InFlag };
181  Chain = DAG.getNode(X86ISD::REP_STOS, dl, Tys, Ops);
182  } else if (BytesLeft) {
183  // Handle the last 1 - 7 bytes.
184  unsigned Offset = SizeVal - BytesLeft;
185  EVT AddrVT = Dst.getValueType();
186  EVT SizeVT = Size.getValueType();
187 
188  Chain = DAG.getMemset(Chain, dl,
189  DAG.getNode(ISD::ADD, dl, AddrVT, Dst,
190  DAG.getConstant(Offset, dl, AddrVT)),
191  Src,
192  DAG.getConstant(BytesLeft, dl, SizeVT),
193  Align, isVolatile, false,
194  DstPtrInfo.getWithOffset(Offset));
195  }
196 
197  // TODO: Use a Tokenfactor, as in memcpy, instead of a single chain.
198  return Chain;
199 }
200 
202  SelectionDAG &DAG, SDLoc dl, SDValue Chain, SDValue Dst, SDValue Src,
203  SDValue Size, unsigned Align, bool isVolatile, bool AlwaysInline,
204  MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const {
205  // This requires the copy size to be a constant, preferably
206  // within a subtarget-specific limit.
207  ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
208  const X86Subtarget &Subtarget =
210  if (!ConstantSize)
211  return SDValue();
212  uint64_t SizeVal = ConstantSize->getZExtValue();
213  if (!AlwaysInline && SizeVal > Subtarget.getMaxInlineSizeThreshold())
214  return SDValue();
215 
216  /// If not DWORD aligned, it is more efficient to call the library. However
217  /// if calling the library is not allowed (AlwaysInline), then soldier on as
218  /// the code generated here is better than the long load-store sequence we
219  /// would otherwise get.
220  if (!AlwaysInline && (Align & 3) != 0)
221  return SDValue();
222 
223  // If to a segment-relative address space, use the default lowering.
224  if (DstPtrInfo.getAddrSpace() >= 256 ||
225  SrcPtrInfo.getAddrSpace() >= 256)
226  return SDValue();
227 
228  // If the base register might conflict with our physical registers, bail out.
229  const unsigned ClobberSet[] = {X86::RCX, X86::RSI, X86::RDI,
230  X86::ECX, X86::ESI, X86::EDI};
231  if (isBaseRegConflictPossible(DAG, ClobberSet))
232  return SDValue();
233 
234  MVT AVT;
235  if (Align & 1)
236  AVT = MVT::i8;
237  else if (Align & 2)
238  AVT = MVT::i16;
239  else if (Align & 4)
240  // DWORD aligned
241  AVT = MVT::i32;
242  else
243  // QWORD aligned
244  AVT = Subtarget.is64Bit() ? MVT::i64 : MVT::i32;
245 
246  unsigned UBytes = AVT.getSizeInBits() / 8;
247  unsigned CountVal = SizeVal / UBytes;
248  SDValue Count = DAG.getIntPtrConstant(CountVal, dl);
249  unsigned BytesLeft = SizeVal % UBytes;
250 
251  SDValue InFlag;
252  Chain = DAG.getCopyToReg(Chain, dl, Subtarget.is64Bit() ? X86::RCX :
253  X86::ECX,
254  Count, InFlag);
255  InFlag = Chain.getValue(1);
256  Chain = DAG.getCopyToReg(Chain, dl, Subtarget.is64Bit() ? X86::RDI :
257  X86::EDI,
258  Dst, InFlag);
259  InFlag = Chain.getValue(1);
260  Chain = DAG.getCopyToReg(Chain, dl, Subtarget.is64Bit() ? X86::RSI :
261  X86::ESI,
262  Src, InFlag);
263  InFlag = Chain.getValue(1);
264 
266  SDValue Ops[] = { Chain, DAG.getValueType(AVT), InFlag };
267  SDValue RepMovs = DAG.getNode(X86ISD::REP_MOVS, dl, Tys, Ops);
268 
269  SmallVector<SDValue, 4> Results;
270  Results.push_back(RepMovs);
271  if (BytesLeft) {
272  // Handle the last 1 - 7 bytes.
273  unsigned Offset = SizeVal - BytesLeft;
274  EVT DstVT = Dst.getValueType();
275  EVT SrcVT = Src.getValueType();
276  EVT SizeVT = Size.getValueType();
277  Results.push_back(DAG.getMemcpy(Chain, dl,
278  DAG.getNode(ISD::ADD, dl, DstVT, Dst,
279  DAG.getConstant(Offset, dl,
280  DstVT)),
281  DAG.getNode(ISD::ADD, dl, SrcVT, Src,
282  DAG.getConstant(Offset, dl,
283  SrcVT)),
284  DAG.getConstant(BytesLeft, dl, SizeVT),
285  Align, isVolatile, AlwaysInline, false,
286  DstPtrInfo.getWithOffset(Offset),
287  SrcPtrInfo.getWithOffset(Offset)));
288  }
289 
290  return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Results);
291 }
CallLoweringInfo & setCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList, unsigned FixedArgs=-1)
SDValue getValue(unsigned R) const
Repeat move, corresponds to X86::REP_MOVSx.
LLVMContext * getContext() const
Definition: SelectionDAG.h:289
SDValue getCopyToReg(SDValue Chain, SDLoc dl, unsigned Reg, SDValue N)
Definition: SelectionDAG.h:522
CallLoweringInfo & setDebugLoc(SDLoc dl)
const TargetSubtargetInfo & getSubtarget() const
Definition: SelectionDAG.h:286
unsigned getSizeInBits() const
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 override
EmitTargetCodeForMemcpy - Emit target-specific code that performs a memcpy.
SDValue getExternalSymbol(const char *Sym, EVT VT)
SDValue getMemcpy(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool isVol, bool AlwaysInline, bool isTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo)
SDValue getMemset(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool isVol, bool isTailCall, MachinePointerInfo DstPtrInfo)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunction & getMachineFunction() const
Definition: SelectionDAG.h:283
CallLoweringInfo & setChain(SDValue InChain)
MachinePointerInfo getWithOffset(int64_t O) const
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted...
SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:191
const DataLayout & getDataLayout() const
Definition: SelectionDAG.h:284
MVT - Machine Value Type.
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
Repeat fill, corresponds to X86::REP_STOSx.
static Type * getVoidTy(LLVMContext &C)
Definition: Type.cpp:225
EVT - Extended Value Type.
Definition: ValueTypes.h:31
std::vector< ArgListEntry > ArgListTy
This structure contains all information that is necessary for lowering calls.
MachinePointerInfo - This class contains a discriminated union of information about pointers in memor...
unsigned getBaseRegister() const
bool bitsGT(EVT VT) const
bitsGT - Return true if this has more bits than VT.
Definition: ValueTypes.h:177
IntegerType * getIntPtrType(LLVMContext &C, unsigned AddressSpace=0) const
Returns an integer type with size at least as big as that of a pointer in the given address space...
Definition: DataLayout.cpp:694
TokenFactor - This node takes multiple tokens as input and produces a single token result...
Definition: ISDOpcodes.h:50
SDValue EmitTargetCodeForMemset(SelectionDAG &DAG, SDLoc dl, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool isVolatile, MachinePointerInfo DstPtrInfo) const override
EmitTargetCodeForMemset - Emit target-specific code that performs a memset.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
Definition: SelectionDAG.h:179
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:861
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
unsigned getAddrSpace() const
getAddrSpace - Return the LLVM IR address space number that this pointer points into.
MachineFrameInfo * getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
static cl::opt< AlignMode > Align(cl::desc("Load/store alignment support"), cl::Hidden, cl::init(NoStrictAlign), cl::values(clEnumValN(StrictAlign,"aarch64-strict-align","Disallow all unaligned memory accesses"), clEnumValN(NoStrictAlign,"aarch64-no-strict-align","Allow unaligned memory accesses"), clEnumValEnd))
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:285
SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:321
unsigned getSizeInBits() const
getSizeInBits - Return the size of the specified value type in bits.
Definition: ValueTypes.h:233
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
EVT getValueType() const
Return the ValueType of the referenced return value.
SDValue getConstant(uint64_t Val, SDLoc DL, EVT VT, bool isTarget=false, bool isOpaque=false)
MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
SDValue getValueType(EVT)
const TargetLowering & getTargetLoweringInfo() const
Definition: SelectionDAG.h:287
bool hasOpaqueSPAdjustment() const
Returns true if the function contains opaque dynamic stack adjustments.
C - The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
static bool isVolatile(Instruction *Inst)
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...
SDValue getIntPtrConstant(uint64_t Val, SDLoc DL, bool isTarget=false)
This file describes how to lower LLVM code to machine code.
uint64_t getZExtValue() const