LLVM 24.0.0git
SystemZSelectionDAGInfo.cpp
Go to the documentation of this file.
1//===-- SystemZSelectionDAGInfo.cpp - SystemZ SelectionDAG Info -----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the SystemZSelectionDAGInfo class.
10//
11//===----------------------------------------------------------------------===//
12
16
17#define GET_SDNODE_DESC
18#include "SystemZGenSDNodeInfo.inc"
19
20using namespace llvm;
21
22#define DEBUG_TYPE "systemz-selectiondag-info"
23
26
27const char *SystemZSelectionDAGInfo::getTargetNodeName(unsigned Opcode) const {
28 switch (static_cast<SystemZISD::NodeType>(Opcode)) {
30 return "SystemZISD::GET_CCMASK";
31 }
32
34}
35
36static unsigned getMemMemLenAdj(unsigned Op) {
37 return Op == SystemZISD::MEMSET_MVC ? 2 : 1;
38}
39
40static SDValue createMemMemNode(SelectionDAG &DAG, const SDLoc &DL, unsigned Op,
41 SDValue Chain, SDValue Dst, SDValue Src,
42 SDValue LenAdj, SDValue Byte) {
43 SDVTList VTs = Op == SystemZISD::CLC ? DAG.getVTList(MVT::i32, MVT::Other)
44 : DAG.getVTList(MVT::Other);
46 if (Op == SystemZISD::MEMSET_MVC)
47 Ops = { Chain, Dst, LenAdj, Byte };
48 else
49 Ops = { Chain, Dst, Src, LenAdj };
50 return DAG.getNode(Op, DL, VTs, Ops);
51}
52
53// Emit a mem-mem operation after subtracting one (or two for memset) from
54// size, which will be added back during pseudo expansion. As the Reg case
55// emitted here may be converted by DAGCombiner into having an Imm length,
56// they are both emitted the same way.
57static SDValue emitMemMemImm(SelectionDAG &DAG, const SDLoc &DL, unsigned Op,
58 SDValue Chain, SDValue Dst, SDValue Src,
59 uint64_t Size, SDValue Byte = SDValue()) {
60 unsigned Adj = getMemMemLenAdj(Op);
61 assert(Size >= Adj && "Adjusted length overflow.");
62 SDValue LenAdj = DAG.getConstant(Size - Adj, DL, Dst.getValueType());
63 return createMemMemNode(DAG, DL, Op, Chain, Dst, Src, LenAdj, Byte);
64}
65
66static SDValue emitMemMemReg(SelectionDAG &DAG, const SDLoc &DL, unsigned Op,
67 SDValue Chain, SDValue Dst, SDValue Src,
68 SDValue Size, SDValue Byte = SDValue()) {
69 int64_t Adj = getMemMemLenAdj(Op);
70 SDValue LenAdj = DAG.getNode(ISD::ADD, DL, MVT::i64,
71 DAG.getZExtOrTrunc(Size, DL, MVT::i64),
72 DAG.getSignedConstant(0 - Adj, DL, MVT::i64));
73 return createMemMemNode(DAG, DL, Op, Chain, Dst, Src, LenAdj, Byte);
74}
75
77 SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Dst, SDValue Src,
78 SDValue Size, Align DstAlign, Align SrcAlign, bool IsVolatile,
79 bool AlwaysInline, MachinePointerInfo DstPtrInfo,
80 MachinePointerInfo SrcPtrInfo) const {
81 if (IsVolatile)
82 return SDValue();
83
84 if (auto *CSize = dyn_cast<ConstantSDNode>(Size))
85 return emitMemMemImm(DAG, DL, SystemZISD::MVC, Chain, Dst, Src,
86 CSize->getZExtValue());
87
88 return emitMemMemReg(DAG, DL, SystemZISD::MVC, Chain, Dst, Src, Size);
89}
90
92 SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Dst, SDValue Src,
93 SDValue Size, Align DstAlign, Align SrcAlign, bool IsVolatile,
94 MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const {
95 if (IsVolatile)
96 return SDValue();
97
98 const SystemZSubtarget &Subtarget =
100
101 if (auto *CSize = dyn_cast<ConstantSDNode>(Size))
102 if (Subtarget.hasMiscellaneousExtensions3() && CSize->getZExtValue() > 0 &&
103 CSize->getZExtValue() <= 256) {
104 SDValue Size64 = DAG.getZExtOrTrunc(Size, DL, MVT::i64);
105 return DAG.getNode(SystemZISD::MEMMOVE, DL, MVT::Other,
106 {Chain, Dst, Src, Size64});
107 }
108
109 return SDValue();
110}
111
112// Handle a memset of 1, 2, 4 or 8 bytes with the operands given by
113// Chain, Dst, ByteVal and Size. These cases are expected to use
114// MVI, MVHHI, MVHI and MVGHI respectively.
115static SDValue memsetStore(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain,
116 SDValue Dst, uint64_t ByteVal, uint64_t Size,
117 Align Alignment, MachinePointerInfo DstPtrInfo) {
118 uint64_t StoreVal = ByteVal;
119 for (unsigned I = 1; I < Size; ++I)
120 StoreVal |= ByteVal << (I * 8);
121 return DAG.getStore(
122 Chain, DL, DAG.getConstant(StoreVal, DL, MVT::getIntegerVT(Size * 8)),
123 Dst, DstPtrInfo, Alignment);
124}
125
127 SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Dst,
128 SDValue Byte, SDValue Size, Align Alignment, bool IsVolatile,
129 bool AlwaysInline, MachinePointerInfo DstPtrInfo) const {
130 EVT PtrVT = Dst.getValueType();
131
132 if (IsVolatile)
133 return SDValue();
134
135 auto *CByte = dyn_cast<ConstantSDNode>(Byte);
136 if (auto *CSize = dyn_cast<ConstantSDNode>(Size)) {
137 uint64_t Bytes = CSize->getZExtValue();
138 if (Bytes == 0)
139 return SDValue();
140 if (CByte) {
141 // Handle cases that can be done using at most two of
142 // MVI, MVHI, MVHHI and MVGHI. The latter two can only be
143 // used if ByteVal is all zeros or all ones; in other cases,
144 // we can move at most 2 halfwords.
145 uint64_t ByteVal = CByte->getZExtValue();
146 if (ByteVal == 0 || ByteVal == 255
147 ? Bytes <= 16 && llvm::popcount(Bytes) <= 2
148 : Bytes <= 4) {
149 unsigned Size1 = Bytes == 16 ? 8 : llvm::bit_floor(Bytes);
150 unsigned Size2 = Bytes - Size1;
151 SDValue Chain1 = memsetStore(DAG, DL, Chain, Dst, ByteVal, Size1,
152 Alignment, DstPtrInfo);
153 if (Size2 == 0)
154 return Chain1;
155 Dst = DAG.getNode(ISD::ADD, DL, PtrVT, Dst,
156 DAG.getConstant(Size1, DL, PtrVT));
157 DstPtrInfo = DstPtrInfo.getWithOffset(Size1);
158 SDValue Chain2 =
159 memsetStore(DAG, DL, Chain, Dst, ByteVal, Size2,
160 std::min(Alignment, Align(Size1)), DstPtrInfo);
161 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chain1, Chain2);
162 }
163 } else {
164 // Handle one and two bytes using STC.
165 if (Bytes <= 2) {
166 SDValue Chain1 =
167 DAG.getStore(Chain, DL, Byte, Dst, DstPtrInfo, Alignment);
168 if (Bytes == 1)
169 return Chain1;
170 SDValue Dst2 = DAG.getNode(ISD::ADD, DL, PtrVT, Dst,
171 DAG.getConstant(1, DL, PtrVT));
172 SDValue Chain2 = DAG.getStore(Chain, DL, Byte, Dst2,
173 DstPtrInfo.getWithOffset(1), Align(1));
174 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chain1, Chain2);
175 }
176 }
177 assert(Bytes >= 2 && "Should have dealt with 0- and 1-byte cases already");
178
179 // Handle the special case of a memset of 0, which can use XC.
180 if (CByte && CByte->getZExtValue() == 0)
181 return emitMemMemImm(DAG, DL, SystemZISD::XC, Chain, Dst, Dst, Bytes);
182
183 return emitMemMemImm(DAG, DL, SystemZISD::MEMSET_MVC, Chain, Dst, SDValue(),
184 Bytes, DAG.getAnyExtOrTrunc(Byte, DL, MVT::i32));
185 }
186
187 // Variable length
188 if (CByte && CByte->getZExtValue() == 0)
189 // Handle the special case of a variable length memset of 0 with XC.
190 return emitMemMemReg(DAG, DL, SystemZISD::XC, Chain, Dst, Dst, Size);
191
192 return emitMemMemReg(DAG, DL, SystemZISD::MEMSET_MVC, Chain, Dst, SDValue(),
193 Size, DAG.getAnyExtOrTrunc(Byte, DL, MVT::i32));
194}
195
196// Convert the current CC value into an integer that is 0 if CC == 0,
197// greater than zero if CC == 1 and less than zero if CC >= 2.
198// The sequence starts with IPM, which puts CC into bits 29 and 28
199// of an integer and clears bits 30 and 31.
200static SDValue addIPMSequence(const SDLoc &DL, SDValue CCReg,
201 SelectionDAG &DAG) {
202 SDValue IPM = DAG.getNode(SystemZISD::IPM, DL, MVT::i32, CCReg);
203 SDValue SHL = DAG.getNode(ISD::SHL, DL, MVT::i32, IPM,
204 DAG.getConstant(30 - SystemZ::IPM_CC, DL, MVT::i32));
205 SDValue SRA = DAG.getNode(ISD::SRA, DL, MVT::i32, SHL,
206 DAG.getConstant(30, DL, MVT::i32));
207 return SRA;
208}
209
211 SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src1,
212 SDValue Src2, SDValue Size, const CallInst *CI) const {
213 SDValue CCReg;
214 // Swap operands to invert CC == 1 vs. CC == 2 cases.
215 if (auto *CSize = dyn_cast<ConstantSDNode>(Size)) {
216 uint64_t Bytes = CSize->getZExtValue();
217 assert(Bytes > 0 && "Caller should have handled 0-size case");
218 CCReg = emitMemMemImm(DAG, DL, SystemZISD::CLC, Chain, Src2, Src1, Bytes);
219 } else
220 CCReg = emitMemMemReg(DAG, DL, SystemZISD::CLC, Chain, Src2, Src1, Size);
221 Chain = CCReg.getValue(1);
222 return std::make_pair(addIPMSequence(DL, CCReg, DAG), Chain);
223}
224
226 SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src,
227 SDValue Char, SDValue Length, MachinePointerInfo SrcPtrInfo) const {
228 // Use SRST to find the character. End is its address on success.
229 EVT PtrVT = Src.getValueType();
230 SDVTList VTs = DAG.getVTList(PtrVT, MVT::i32, MVT::Other);
231 Length = DAG.getZExtOrTrunc(Length, DL, PtrVT);
232 Char = DAG.getZExtOrTrunc(Char, DL, MVT::i32);
233 Char = DAG.getNode(ISD::AND, DL, MVT::i32, Char,
234 DAG.getConstant(255, DL, MVT::i32));
235 SDValue Limit = DAG.getNode(ISD::ADD, DL, PtrVT, Src, Length);
236 SDValue End = DAG.getNode(SystemZISD::SEARCH_STRING, DL, VTs, Chain,
237 Limit, Src, Char);
238 SDValue CCReg = End.getValue(1);
239 Chain = End.getValue(2);
240
241 // Now select between End and null, depending on whether the character
242 // was found.
243 SDValue Ops[] = {
244 End, DAG.getConstant(0, DL, PtrVT),
246 DAG.getTargetConstant(SystemZ::CCMASK_SRST_FOUND, DL, MVT::i32), CCReg};
247 End = DAG.getNode(SystemZISD::SELECT_CCMASK, DL, PtrVT, Ops);
248 return std::make_pair(End, Chain);
249}
250
252 SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Dest,
253 SDValue Src, MachinePointerInfo DestPtrInfo, MachinePointerInfo SrcPtrInfo,
254 bool isStpcpy, const CallInst *CI) const {
255 SDVTList VTs = DAG.getVTList(Dest.getValueType(), MVT::Other);
256 SDValue EndDest = DAG.getNode(SystemZISD::STPCPY, DL, VTs, Chain, Dest, Src,
257 DAG.getConstant(0, DL, MVT::i32));
258 return std::make_pair(isStpcpy ? EndDest : Dest, EndDest.getValue(1));
259}
260
262 SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src1,
263 SDValue Src2, MachinePointerInfo Op1PtrInfo, MachinePointerInfo Op2PtrInfo,
264 const CallInst *CI) const {
265 SDVTList VTs = DAG.getVTList(Src1.getValueType(), MVT::i32, MVT::Other);
266 // Swap operands to invert CC == 1 vs. CC == 2 cases.
267 SDValue Unused = DAG.getNode(SystemZISD::STRCMP, DL, VTs, Chain, Src2, Src1,
268 DAG.getConstant(0, DL, MVT::i32));
269 SDValue CCReg = Unused.getValue(1);
270 Chain = Unused.getValue(2);
271 return std::make_pair(addIPMSequence(DL, CCReg, DAG), Chain);
272}
273
274// Search from Src for a null character, stopping once Src reaches Limit.
275// Return a pair of values, the first being the number of nonnull characters
276// and the second being the out chain.
277//
278// This can be used for strlen by setting Limit to 0.
279static std::pair<SDValue, SDValue> getBoundedStrlen(SelectionDAG &DAG,
280 const SDLoc &DL,
281 SDValue Chain, SDValue Src,
282 SDValue Limit) {
283 EVT PtrVT = Src.getValueType();
284 SDVTList VTs = DAG.getVTList(PtrVT, MVT::i32, MVT::Other);
285 SDValue End = DAG.getNode(SystemZISD::SEARCH_STRING, DL, VTs, Chain,
286 Limit, Src, DAG.getConstant(0, DL, MVT::i32));
287 Chain = End.getValue(2);
288 SDValue Len = DAG.getNode(ISD::SUB, DL, PtrVT, End, Src);
289 return std::make_pair(Len, Chain);
290}
291
293 SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src,
294 const CallInst *CI) const {
295 EVT PtrVT = Src.getValueType();
296 return getBoundedStrlen(DAG, DL, Chain, Src, DAG.getConstant(0, DL, PtrVT));
297}
298
300 SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src,
301 SDValue MaxLength, MachinePointerInfo SrcPtrInfo) const {
302 EVT PtrVT = Src.getValueType();
303 MaxLength = DAG.getZExtOrTrunc(MaxLength, DL, PtrVT);
304 SDValue Limit = DAG.getNode(ISD::ADD, DL, PtrVT, Src, MaxLength);
305 return getBoundedStrlen(DAG, DL, Chain, Src, Limit);
306}
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define I(x, y, z)
Definition MD5.cpp:57
static SDValue emitMemMemReg(SelectionDAG &DAG, const SDLoc &DL, unsigned Op, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, SDValue Byte=SDValue())
static std::pair< SDValue, SDValue > getBoundedStrlen(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src, SDValue Limit)
static unsigned getMemMemLenAdj(unsigned Op)
static SDValue addIPMSequence(const SDLoc &DL, SDValue CCReg, SelectionDAG &DAG)
static SDValue memsetStore(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Dst, uint64_t ByteVal, uint64_t Size, Align Alignment, MachinePointerInfo DstPtrInfo)
static SDValue createMemMemNode(SelectionDAG &DAG, const SDLoc &DL, unsigned Op, SDValue Chain, SDValue Dst, SDValue Src, SDValue LenAdj, SDValue Byte)
static SDValue emitMemMemImm(SelectionDAG &DAG, const SDLoc &DL, unsigned Op, SDValue Chain, SDValue Dst, SDValue Src, uint64_t Size, SDValue Byte=SDValue())
This class represents a function call, abstracting a target machine's calling convention.
static MVT getIntegerVT(unsigned BitWidth)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const char * getTargetNodeName(unsigned Opcode) const override
Returns the name of the given target-specific opcode, suitable for debug printing.
SelectionDAGGenTargetInfo(const SDNodeInfo &GenNodeInfo)
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
MachineFunction & getMachineFunction() const
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
const char * getTargetNodeName(unsigned Opcode) const override
Returns the name of the given target-specific opcode, suitable for debug printing.
SDValue EmitTargetCodeForMemset(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Dst, SDValue Byte, SDValue Size, Align Alignment, bool IsVolatile, bool AlwaysInline, MachinePointerInfo DstPtrInfo) const override
Emit target-specific code that performs a memset.
std::pair< SDValue, SDValue > EmitTargetCodeForMemchr(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src, SDValue Char, SDValue Length, MachinePointerInfo SrcPtrInfo) const override
Emit target-specific code that performs a memchr, in cases where that is faster than a libcall.
std::pair< SDValue, SDValue > EmitTargetCodeForMemcmp(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src1, SDValue Src2, SDValue Size, const CallInst *CI) const override
Emit target-specific code that performs a memcmp/bcmp, in cases where that is faster than a libcall.
SDValue EmitTargetCodeForMemcpy(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, Align DstAlign, Align SrcAlign, bool IsVolatile, bool AlwaysInline, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const override
Emit target-specific code that performs a memcpy.
SDValue EmitTargetCodeForMemmove(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, Align DstAlign, Align SrcAlign, bool IsVolatile, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const override
Emit target-specific code that performs a memmove.
std::pair< SDValue, SDValue > EmitTargetCodeForStrnlen(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src, SDValue MaxLength, MachinePointerInfo SrcPtrInfo) const override
std::pair< SDValue, SDValue > EmitTargetCodeForStrlen(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src, const CallInst *CI) const override
std::pair< SDValue, SDValue > EmitTargetCodeForStrcpy(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Dest, SDValue Src, MachinePointerInfo DestPtrInfo, MachinePointerInfo SrcPtrInfo, bool isStpcpy, const CallInst *CI) const override
Emit target-specific code that performs a strcpy or stpcpy, in cases where that is faster than a libc...
std::pair< SDValue, SDValue > EmitTargetCodeForStrcmp(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src1, SDValue Src2, MachinePointerInfo Op1PtrInfo, MachinePointerInfo Op2PtrInfo, const CallInst *CI) const override
Emit target-specific code that performs a strcmp, in cases where that is faster than a libcall.
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:264
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:771
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:741
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition ISDOpcodes.h:53
const unsigned CCMASK_SRST
Definition SystemZ.h:75
const unsigned CCMASK_SRST_FOUND
Definition SystemZ.h:73
const unsigned IPM_CC
Definition SystemZ.h:113
This is an optimization pass for GlobalISel generic memory operations.
@ Length
Definition DWP.cpp:578
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
DWARFExpression::Operation Op
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
Definition bit.h:347
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Extended Value Type.
Definition ValueTypes.h:35
This class contains a discriminated union of information about pointers in memory operands,...
MachinePointerInfo getWithOffset(int64_t O) const
This represents a list of ValueType's that has been intern'd by a SelectionDAG.