LLVM  3.7.0
SystemZSelectionDAGInfo.cpp
Go to the documentation of this file.
1 //===-- SystemZSelectionDAGInfo.cpp - SystemZ 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 SystemZSelectionDAGInfo class.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "SystemZTargetMachine.h"
16 
17 using namespace llvm;
18 
19 #define DEBUG_TYPE "systemz-selectiondag-info"
20 
21 // Decide whether it is best to use a loop or straight-line code for
22 // a block operation of Size bytes with source address Src and destination
23 // address Dest. Sequence is the opcode to use for straight-line code
24 // (such as MVC) and Loop is the opcode to use for loops (such as MVC_LOOP).
25 // Return the chain for the completed operation.
26 static SDValue emitMemMem(SelectionDAG &DAG, SDLoc DL, unsigned Sequence,
27  unsigned Loop, SDValue Chain, SDValue Dst,
28  SDValue Src, uint64_t Size) {
29  EVT PtrVT = Src.getValueType();
30  // The heuristic we use is to prefer loops for anything that would
31  // require 7 or more MVCs. With these kinds of sizes there isn't
32  // much to choose between straight-line code and looping code,
33  // since the time will be dominated by the MVCs themselves.
34  // However, the loop has 4 or 5 instructions (depending on whether
35  // the base addresses can be proved equal), so there doesn't seem
36  // much point using a loop for 5 * 256 bytes or fewer. Anything in
37  // the range (5 * 256, 6 * 256) will need another instruction after
38  // the loop, so it doesn't seem worth using a loop then either.
39  // The next value up, 6 * 256, can be implemented in the same
40  // number of straight-line MVCs as 6 * 256 - 1.
41  if (Size > 6 * 256)
42  return DAG.getNode(Loop, DL, MVT::Other, Chain, Dst, Src,
43  DAG.getConstant(Size, DL, PtrVT),
44  DAG.getConstant(Size / 256, DL, PtrVT));
45  return DAG.getNode(Sequence, DL, MVT::Other, Chain, Dst, Src,
46  DAG.getConstant(Size, DL, PtrVT));
47 }
48 
51  SDValue Dst, SDValue Src, SDValue Size, unsigned Align,
52  bool IsVolatile, bool AlwaysInline,
53  MachinePointerInfo DstPtrInfo,
54  MachinePointerInfo SrcPtrInfo) const {
55  if (IsVolatile)
56  return SDValue();
57 
58  if (auto *CSize = dyn_cast<ConstantSDNode>(Size))
60  Chain, Dst, Src, CSize->getZExtValue());
61  return SDValue();
62 }
63 
64 // Handle a memset of 1, 2, 4 or 8 bytes with the operands given by
65 // Chain, Dst, ByteVal and Size. These cases are expected to use
66 // MVI, MVHHI, MVHI and MVGHI respectively.
67 static SDValue memsetStore(SelectionDAG &DAG, SDLoc DL, SDValue Chain,
68  SDValue Dst, uint64_t ByteVal, uint64_t Size,
69  unsigned Align,
70  MachinePointerInfo DstPtrInfo) {
71  uint64_t StoreVal = ByteVal;
72  for (unsigned I = 1; I < Size; ++I)
73  StoreVal |= ByteVal << (I * 8);
74  return DAG.getStore(Chain, DL,
75  DAG.getConstant(StoreVal, DL,
76  MVT::getIntegerVT(Size * 8)),
77  Dst, DstPtrInfo, false, false, Align);
78 }
79 
82  SDValue Dst, SDValue Byte, SDValue Size,
83  unsigned Align, bool IsVolatile,
84  MachinePointerInfo DstPtrInfo) const {
85  EVT PtrVT = Dst.getValueType();
86 
87  if (IsVolatile)
88  return SDValue();
89 
90  if (auto *CSize = dyn_cast<ConstantSDNode>(Size)) {
91  uint64_t Bytes = CSize->getZExtValue();
92  if (Bytes == 0)
93  return SDValue();
94  if (auto *CByte = dyn_cast<ConstantSDNode>(Byte)) {
95  // Handle cases that can be done using at most two of
96  // MVI, MVHI, MVHHI and MVGHI. The latter two can only be
97  // used if ByteVal is all zeros or all ones; in other casees,
98  // we can move at most 2 halfwords.
99  uint64_t ByteVal = CByte->getZExtValue();
100  if (ByteVal == 0 || ByteVal == 255 ?
101  Bytes <= 16 && countPopulation(Bytes) <= 2 :
102  Bytes <= 4) {
103  unsigned Size1 = Bytes == 16 ? 8 : 1 << findLastSet(Bytes);
104  unsigned Size2 = Bytes - Size1;
105  SDValue Chain1 = memsetStore(DAG, DL, Chain, Dst, ByteVal, Size1,
106  Align, DstPtrInfo);
107  if (Size2 == 0)
108  return Chain1;
109  Dst = DAG.getNode(ISD::ADD, DL, PtrVT, Dst,
110  DAG.getConstant(Size1, DL, PtrVT));
111  DstPtrInfo = DstPtrInfo.getWithOffset(Size1);
112  SDValue Chain2 = memsetStore(DAG, DL, Chain, Dst, ByteVal, Size2,
113  std::min(Align, Size1), DstPtrInfo);
114  return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chain1, Chain2);
115  }
116  } else {
117  // Handle one and two bytes using STC.
118  if (Bytes <= 2) {
119  SDValue Chain1 = DAG.getStore(Chain, DL, Byte, Dst, DstPtrInfo,
120  false, false, Align);
121  if (Bytes == 1)
122  return Chain1;
123  SDValue Dst2 = DAG.getNode(ISD::ADD, DL, PtrVT, Dst,
124  DAG.getConstant(1, DL, PtrVT));
125  SDValue Chain2 = DAG.getStore(Chain, DL, Byte, Dst2,
126  DstPtrInfo.getWithOffset(1),
127  false, false, 1);
128  return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chain1, Chain2);
129  }
130  }
131  assert(Bytes >= 2 && "Should have dealt with 0- and 1-byte cases already");
132 
133  // Handle the special case of a memset of 0, which can use XC.
134  auto *CByte = dyn_cast<ConstantSDNode>(Byte);
135  if (CByte && CByte->getZExtValue() == 0)
137  Chain, Dst, Dst, Bytes);
138 
139  // Copy the byte to the first location and then use MVC to copy
140  // it to the rest.
141  Chain = DAG.getStore(Chain, DL, Byte, Dst, DstPtrInfo,
142  false, false, Align);
143  SDValue DstPlus1 = DAG.getNode(ISD::ADD, DL, PtrVT, Dst,
144  DAG.getConstant(1, DL, PtrVT));
146  Chain, DstPlus1, Dst, Bytes - 1);
147  }
148  return SDValue();
149 }
150 
151 // Use CLC to compare [Src1, Src1 + Size) with [Src2, Src2 + Size),
152 // deciding whether to use a loop or straight-line code.
153 static SDValue emitCLC(SelectionDAG &DAG, SDLoc DL, SDValue Chain,
154  SDValue Src1, SDValue Src2, uint64_t Size) {
156  EVT PtrVT = Src1.getValueType();
157  // A two-CLC sequence is a clear win over a loop, not least because it
158  // needs only one branch. A three-CLC sequence needs the same number
159  // of branches as a loop (i.e. 2), but is shorter. That brings us to
160  // lengths greater than 768 bytes. It seems relatively likely that
161  // a difference will be found within the first 768 bytes, so we just
162  // optimize for the smallest number of branch instructions, in order
163  // to avoid polluting the prediction buffer too much. A loop only ever
164  // needs 2 branches, whereas a straight-line sequence would need 3 or more.
165  if (Size > 3 * 256)
166  return DAG.getNode(SystemZISD::CLC_LOOP, DL, VTs, Chain, Src1, Src2,
167  DAG.getConstant(Size, DL, PtrVT),
168  DAG.getConstant(Size / 256, DL, PtrVT));
169  return DAG.getNode(SystemZISD::CLC, DL, VTs, Chain, Src1, Src2,
170  DAG.getConstant(Size, DL, PtrVT));
171 }
172 
173 // Convert the current CC value into an integer that is 0 if CC == 0,
174 // less than zero if CC == 1 and greater than zero if CC >= 2.
175 // The sequence starts with IPM, which puts CC into bits 29 and 28
176 // of an integer and clears bits 30 and 31.
178  SDValue IPM = DAG.getNode(SystemZISD::IPM, DL, MVT::i32, Glue);
179  SDValue SRL = DAG.getNode(ISD::SRL, DL, MVT::i32, IPM,
181  SDValue ROTL = DAG.getNode(ISD::ROTL, DL, MVT::i32, SRL,
182  DAG.getConstant(31, DL, MVT::i32));
183  return ROTL;
184 }
185 
186 std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::
188  SDValue Src1, SDValue Src2, SDValue Size,
189  MachinePointerInfo Op1PtrInfo,
190  MachinePointerInfo Op2PtrInfo) const {
191  if (auto *CSize = dyn_cast<ConstantSDNode>(Size)) {
192  uint64_t Bytes = CSize->getZExtValue();
193  assert(Bytes > 0 && "Caller should have handled 0-size case");
194  Chain = emitCLC(DAG, DL, Chain, Src1, Src2, Bytes);
195  SDValue Glue = Chain.getValue(1);
196  return std::make_pair(addIPMSequence(DL, Glue, DAG), Chain);
197  }
198  return std::make_pair(SDValue(), SDValue());
199 }
200 
201 std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::
203  SDValue Src, SDValue Char, SDValue Length,
204  MachinePointerInfo SrcPtrInfo) const {
205  // Use SRST to find the character. End is its address on success.
206  EVT PtrVT = Src.getValueType();
207  SDVTList VTs = DAG.getVTList(PtrVT, MVT::Other, MVT::Glue);
208  Length = DAG.getZExtOrTrunc(Length, DL, PtrVT);
209  Char = DAG.getZExtOrTrunc(Char, DL, MVT::i32);
210  Char = DAG.getNode(ISD::AND, DL, MVT::i32, Char,
211  DAG.getConstant(255, DL, MVT::i32));
212  SDValue Limit = DAG.getNode(ISD::ADD, DL, PtrVT, Src, Length);
213  SDValue End = DAG.getNode(SystemZISD::SEARCH_STRING, DL, VTs, Chain,
214  Limit, Src, Char);
215  Chain = End.getValue(1);
216  SDValue Glue = End.getValue(2);
217 
218  // Now select between End and null, depending on whether the character
219  // was found.
220  SDValue Ops[] = {End, DAG.getConstant(0, DL, PtrVT),
223  Glue};
224  VTs = DAG.getVTList(PtrVT, MVT::Glue);
225  End = DAG.getNode(SystemZISD::SELECT_CCMASK, DL, VTs, Ops);
226  return std::make_pair(End, Chain);
227 }
228 
229 std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::
231  SDValue Dest, SDValue Src,
232  MachinePointerInfo DestPtrInfo,
233  MachinePointerInfo SrcPtrInfo, bool isStpcpy) const {
234  SDVTList VTs = DAG.getVTList(Dest.getValueType(), MVT::Other);
235  SDValue EndDest = DAG.getNode(SystemZISD::STPCPY, DL, VTs, Chain, Dest, Src,
236  DAG.getConstant(0, DL, MVT::i32));
237  return std::make_pair(isStpcpy ? EndDest : Dest, EndDest.getValue(1));
238 }
239 
240 std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::
242  SDValue Src1, SDValue Src2,
243  MachinePointerInfo Op1PtrInfo,
244  MachinePointerInfo Op2PtrInfo) const {
245  SDVTList VTs = DAG.getVTList(Src1.getValueType(), MVT::Other, MVT::Glue);
246  SDValue Unused = DAG.getNode(SystemZISD::STRCMP, DL, VTs, Chain, Src1, Src2,
247  DAG.getConstant(0, DL, MVT::i32));
248  Chain = Unused.getValue(1);
249  SDValue Glue = Chain.getValue(2);
250  return std::make_pair(addIPMSequence(DL, Glue, DAG), Chain);
251 }
252 
253 // Search from Src for a null character, stopping once Src reaches Limit.
254 // Return a pair of values, the first being the number of nonnull characters
255 // and the second being the out chain.
256 //
257 // This can be used for strlen by setting Limit to 0.
258 static std::pair<SDValue, SDValue> getBoundedStrlen(SelectionDAG &DAG, SDLoc DL,
259  SDValue Chain, SDValue Src,
260  SDValue Limit) {
261  EVT PtrVT = Src.getValueType();
262  SDVTList VTs = DAG.getVTList(PtrVT, MVT::Other, MVT::Glue);
263  SDValue End = DAG.getNode(SystemZISD::SEARCH_STRING, DL, VTs, Chain,
264  Limit, Src, DAG.getConstant(0, DL, MVT::i32));
265  Chain = End.getValue(1);
266  SDValue Len = DAG.getNode(ISD::SUB, DL, PtrVT, End, Src);
267  return std::make_pair(Len, Chain);
268 }
269 
270 std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::
272  SDValue Src, MachinePointerInfo SrcPtrInfo) const {
273  EVT PtrVT = Src.getValueType();
274  return getBoundedStrlen(DAG, DL, Chain, Src, DAG.getConstant(0, DL, PtrVT));
275 }
276 
277 std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::
279  SDValue Src, SDValue MaxLength,
280  MachinePointerInfo SrcPtrInfo) const {
281  EVT PtrVT = Src.getValueType();
282  MaxLength = DAG.getZExtOrTrunc(MaxLength, DL, PtrVT);
283  SDValue Limit = DAG.getNode(ISD::ADD, DL, PtrVT, Src, MaxLength);
284  return getBoundedStrlen(DAG, DL, Chain, Src, Limit);
285 }
static MVT getIntegerVT(unsigned BitWidth)
SDValue getValue(unsigned R) const
T findLastSet(T Val, ZeroBehavior ZB=ZB_Max)
Get the index of the last set bit starting from the least significant bit.
Definition: MathExtras.h:206
static SDValue emitCLC(SelectionDAG &DAG, SDLoc DL, SDValue Chain, SDValue Src1, SDValue Src2, uint64_t Size)
static SDValue memsetStore(SelectionDAG &DAG, SDLoc DL, SDValue Chain, SDValue Dst, uint64_t ByteVal, uint64_t Size, unsigned Align, MachinePointerInfo DstPtrInfo)
SDValue getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, bool isVolatile, bool isNonTemporal, unsigned Alignment, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
MachinePointerInfo getWithOffset(int64_t O) const
static SDValue addIPMSequence(SDLoc DL, SDValue Glue, SelectionDAG &DAG)
Number of individual test Apply this number of consecutive mutations to each input exit after the first new interesting input is found the minimized corpus is saved into the first input directory Number of jobs to run If min(jobs, NumberOfCpuCores()/2)\" is used.") FUZZER_FLAG_INT(reload
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.
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:191
std::pair< SDValue, SDValue > EmitTargetCodeForStrlen(SelectionDAG &DAG, SDLoc DL, SDValue Chain, SDValue Src, MachinePointerInfo SrcPtrInfo) const override
static std::pair< SDValue, SDValue > getBoundedStrlen(SelectionDAG &DAG, SDLoc DL, SDValue Chain, SDValue Src, SDValue Limit)
std::pair< SDValue, SDValue > EmitTargetCodeForMemcmp(SelectionDAG &DAG, SDLoc DL, SDValue Chain, SDValue Src1, SDValue Src2, SDValue Size, MachinePointerInfo Op1PtrInfo, MachinePointerInfo Op2PtrInfo) const override
EmitTargetCodeForMemcmp - Emit target-specific code that performs a memcmp, in cases where that is fa...
SDValue EmitTargetCodeForMemset(SelectionDAG &DAG, SDLoc DL, SDValue Chain, SDValue Dst, SDValue Byte, SDValue Size, unsigned Align, bool IsVolatile, MachinePointerInfo DstPtrInfo) const override
EmitTargetCodeForMemset - Emit target-specific code that performs a memset.
EVT - Extended Value Type.
Definition: ValueTypes.h:31
MachinePointerInfo - This class contains a discriminated union of information about pointers in memor...
const unsigned CCMASK_SRST_FOUND
Definition: SystemZ.h:56
TokenFactor - This node takes multiple tokens as input and produces a single token result...
Definition: ISDOpcodes.h:50
unsigned countPopulation(T Value)
Count the number of set bits in a value.
Definition: MathExtras.h:449
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
Definition: SelectionDAG.h:179
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
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))
std::pair< SDValue, SDValue > EmitTargetCodeForStrcmp(SelectionDAG &DAG, SDLoc DL, SDValue Chain, SDValue Src1, SDValue Src2, MachinePointerInfo Op1PtrInfo, MachinePointerInfo Op2PtrInfo) const override
EmitTargetCodeForStrcmp - Emit target-specific code that performs a strcmp, in cases where that is fa...
const unsigned CCMASK_SRST
Definition: SystemZ.h:58
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.
std::pair< SDValue, SDValue > EmitTargetCodeForStrnlen(SelectionDAG &DAG, SDLoc DL, SDValue Chain, SDValue Src, SDValue MaxLength, MachinePointerInfo SrcPtrInfo) const override
std::pair< SDValue, SDValue > EmitTargetCodeForStrcpy(SelectionDAG &DAG, SDLoc DL, SDValue Chain, SDValue Dest, SDValue Src, MachinePointerInfo DestPtrInfo, MachinePointerInfo SrcPtrInfo, bool isStpcpy) const override
EmitTargetCodeForStrcpy - Emit target-specific code that performs a strcpy or stpcpy, in cases where that is faster than a libcall.
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:321
static SDValue emitMemMem(SelectionDAG &DAG, SDLoc DL, unsigned Sequence, unsigned Loop, SDValue Chain, SDValue Dst, SDValue Src, uint64_t Size)
#define I(x, y, z)
Definition: MD5.cpp:54
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
Definition: PtrState.h:37
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)
SDValue getZExtOrTrunc(SDValue Op, SDLoc DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
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.
const unsigned IPM_CC
Definition: SystemZ.h:91
std::pair< SDValue, SDValue > EmitTargetCodeForMemchr(SelectionDAG &DAG, SDLoc DL, SDValue Chain, SDValue Src, SDValue Char, SDValue Length, MachinePointerInfo SrcPtrInfo) const override
EmitTargetCodeForMemchr - Emit target-specific code that performs a memchr, in cases where that is fa...
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...