LLVM 20.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
15
16using namespace llvm;
17
18#define DEBUG_TYPE "systemz-selectiondag-info"
19
20static unsigned getMemMemLenAdj(unsigned Op) {
21 return Op == SystemZISD::MEMSET_MVC ? 2 : 1;
22}
23
24static SDValue createMemMemNode(SelectionDAG &DAG, const SDLoc &DL, unsigned Op,
25 SDValue Chain, SDValue Dst, SDValue Src,
26 SDValue LenAdj, SDValue Byte) {
27 SDVTList VTs = Op == SystemZISD::CLC ? DAG.getVTList(MVT::i32, MVT::Other)
28 : DAG.getVTList(MVT::Other);
31 Ops = { Chain, Dst, LenAdj, Byte };
32 else
33 Ops = { Chain, Dst, Src, LenAdj };
34 return DAG.getNode(Op, DL, VTs, Ops);
35}
36
37// Emit a mem-mem operation after subtracting one (or two for memset) from
38// size, which will be added back during pseudo expansion. As the Reg case
39// emitted here may be converted by DAGCombiner into having an Imm length,
40// they are both emitted the same way.
41static SDValue emitMemMemImm(SelectionDAG &DAG, const SDLoc &DL, unsigned Op,
42 SDValue Chain, SDValue Dst, SDValue Src,
43 uint64_t Size, SDValue Byte = SDValue()) {
44 unsigned Adj = getMemMemLenAdj(Op);
45 assert(Size >= Adj && "Adjusted length overflow.");
46 SDValue LenAdj = DAG.getConstant(Size - Adj, DL, Dst.getValueType());
47 return createMemMemNode(DAG, DL, Op, Chain, Dst, Src, LenAdj, Byte);
48}
49
50static SDValue emitMemMemReg(SelectionDAG &DAG, const SDLoc &DL, unsigned Op,
51 SDValue Chain, SDValue Dst, SDValue Src,
52 SDValue Size, SDValue Byte = SDValue()) {
53 int64_t Adj = getMemMemLenAdj(Op);
54 SDValue LenAdj = DAG.getNode(ISD::ADD, DL, MVT::i64,
55 DAG.getZExtOrTrunc(Size, DL, MVT::i64),
56 DAG.getSignedConstant(0 - Adj, DL, MVT::i64));
57 return createMemMemNode(DAG, DL, Op, Chain, Dst, Src, LenAdj, Byte);
58}
59
61 SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Dst, SDValue Src,
62 SDValue Size, Align Alignment, bool IsVolatile, bool AlwaysInline,
63 MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const {
64 if (IsVolatile)
65 return SDValue();
66
67 if (auto *CSize = dyn_cast<ConstantSDNode>(Size))
68 return emitMemMemImm(DAG, DL, SystemZISD::MVC, Chain, Dst, Src,
69 CSize->getZExtValue());
70
71 return emitMemMemReg(DAG, DL, SystemZISD::MVC, Chain, Dst, Src, Size);
72}
73
74// Handle a memset of 1, 2, 4 or 8 bytes with the operands given by
75// Chain, Dst, ByteVal and Size. These cases are expected to use
76// MVI, MVHHI, MVHI and MVGHI respectively.
77static SDValue memsetStore(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain,
78 SDValue Dst, uint64_t ByteVal, uint64_t Size,
79 Align Alignment, MachinePointerInfo DstPtrInfo) {
80 uint64_t StoreVal = ByteVal;
81 for (unsigned I = 1; I < Size; ++I)
82 StoreVal |= ByteVal << (I * 8);
83 return DAG.getStore(
84 Chain, DL, DAG.getConstant(StoreVal, DL, MVT::getIntegerVT(Size * 8)),
85 Dst, DstPtrInfo, Alignment);
86}
87
89 SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Dst,
90 SDValue Byte, SDValue Size, Align Alignment, bool IsVolatile,
91 bool AlwaysInline, MachinePointerInfo DstPtrInfo) const {
92 EVT PtrVT = Dst.getValueType();
93
94 if (IsVolatile)
95 return SDValue();
96
97 auto *CByte = dyn_cast<ConstantSDNode>(Byte);
98 if (auto *CSize = dyn_cast<ConstantSDNode>(Size)) {
99 uint64_t Bytes = CSize->getZExtValue();
100 if (Bytes == 0)
101 return SDValue();
102 if (CByte) {
103 // Handle cases that can be done using at most two of
104 // MVI, MVHI, MVHHI and MVGHI. The latter two can only be
105 // used if ByteVal is all zeros or all ones; in other cases,
106 // we can move at most 2 halfwords.
107 uint64_t ByteVal = CByte->getZExtValue();
108 if (ByteVal == 0 || ByteVal == 255
109 ? Bytes <= 16 && llvm::popcount(Bytes) <= 2
110 : Bytes <= 4) {
111 unsigned Size1 = Bytes == 16 ? 8 : llvm::bit_floor(Bytes);
112 unsigned Size2 = Bytes - Size1;
113 SDValue Chain1 = memsetStore(DAG, DL, Chain, Dst, ByteVal, Size1,
114 Alignment, DstPtrInfo);
115 if (Size2 == 0)
116 return Chain1;
117 Dst = DAG.getNode(ISD::ADD, DL, PtrVT, Dst,
118 DAG.getConstant(Size1, DL, PtrVT));
119 DstPtrInfo = DstPtrInfo.getWithOffset(Size1);
120 SDValue Chain2 =
121 memsetStore(DAG, DL, Chain, Dst, ByteVal, Size2,
122 std::min(Alignment, Align(Size1)), DstPtrInfo);
123 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chain1, Chain2);
124 }
125 } else {
126 // Handle one and two bytes using STC.
127 if (Bytes <= 2) {
128 SDValue Chain1 =
129 DAG.getStore(Chain, DL, Byte, Dst, DstPtrInfo, Alignment);
130 if (Bytes == 1)
131 return Chain1;
132 SDValue Dst2 = DAG.getNode(ISD::ADD, DL, PtrVT, Dst,
133 DAG.getConstant(1, DL, PtrVT));
134 SDValue Chain2 = DAG.getStore(Chain, DL, Byte, Dst2,
135 DstPtrInfo.getWithOffset(1), Align(1));
136 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chain1, Chain2);
137 }
138 }
139 assert(Bytes >= 2 && "Should have dealt with 0- and 1-byte cases already");
140
141 // Handle the special case of a memset of 0, which can use XC.
142 if (CByte && CByte->getZExtValue() == 0)
143 return emitMemMemImm(DAG, DL, SystemZISD::XC, Chain, Dst, Dst, Bytes);
144
145 return emitMemMemImm(DAG, DL, SystemZISD::MEMSET_MVC, Chain, Dst, SDValue(),
146 Bytes, DAG.getAnyExtOrTrunc(Byte, DL, MVT::i32));
147 }
148
149 // Variable length
150 if (CByte && CByte->getZExtValue() == 0)
151 // Handle the special case of a variable length memset of 0 with XC.
152 return emitMemMemReg(DAG, DL, SystemZISD::XC, Chain, Dst, Dst, Size);
153
154 return emitMemMemReg(DAG, DL, SystemZISD::MEMSET_MVC, Chain, Dst, SDValue(),
155 Size, DAG.getAnyExtOrTrunc(Byte, DL, MVT::i32));
156}
157
158// Convert the current CC value into an integer that is 0 if CC == 0,
159// greater than zero if CC == 1 and less than zero if CC >= 2.
160// The sequence starts with IPM, which puts CC into bits 29 and 28
161// of an integer and clears bits 30 and 31.
162static SDValue addIPMSequence(const SDLoc &DL, SDValue CCReg,
163 SelectionDAG &DAG) {
164 SDValue IPM = DAG.getNode(SystemZISD::IPM, DL, MVT::i32, CCReg);
165 SDValue SHL = DAG.getNode(ISD::SHL, DL, MVT::i32, IPM,
166 DAG.getConstant(30 - SystemZ::IPM_CC, DL, MVT::i32));
167 SDValue SRA = DAG.getNode(ISD::SRA, DL, MVT::i32, SHL,
168 DAG.getConstant(30, DL, MVT::i32));
169 return SRA;
170}
171
173 SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src1,
174 SDValue Src2, SDValue Size, MachinePointerInfo Op1PtrInfo,
175 MachinePointerInfo Op2PtrInfo) const {
176 SDValue CCReg;
177 // Swap operands to invert CC == 1 vs. CC == 2 cases.
178 if (auto *CSize = dyn_cast<ConstantSDNode>(Size)) {
179 uint64_t Bytes = CSize->getZExtValue();
180 assert(Bytes > 0 && "Caller should have handled 0-size case");
181 CCReg = emitMemMemImm(DAG, DL, SystemZISD::CLC, Chain, Src2, Src1, Bytes);
182 } else
183 CCReg = emitMemMemReg(DAG, DL, SystemZISD::CLC, Chain, Src2, Src1, Size);
184 Chain = CCReg.getValue(1);
185 return std::make_pair(addIPMSequence(DL, CCReg, DAG), Chain);
186}
187
189 SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src,
190 SDValue Char, SDValue Length, MachinePointerInfo SrcPtrInfo) const {
191 // Use SRST to find the character. End is its address on success.
192 EVT PtrVT = Src.getValueType();
193 SDVTList VTs = DAG.getVTList(PtrVT, MVT::i32, MVT::Other);
194 Length = DAG.getZExtOrTrunc(Length, DL, PtrVT);
195 Char = DAG.getZExtOrTrunc(Char, DL, MVT::i32);
196 Char = DAG.getNode(ISD::AND, DL, MVT::i32, Char,
197 DAG.getConstant(255, DL, MVT::i32));
198 SDValue Limit = DAG.getNode(ISD::ADD, DL, PtrVT, Src, Length);
200 Limit, Src, Char);
201 SDValue CCReg = End.getValue(1);
202 Chain = End.getValue(2);
203
204 // Now select between End and null, depending on whether the character
205 // was found.
206 SDValue Ops[] = {
207 End, DAG.getConstant(0, DL, PtrVT),
209 DAG.getTargetConstant(SystemZ::CCMASK_SRST_FOUND, DL, MVT::i32), CCReg};
210 End = DAG.getNode(SystemZISD::SELECT_CCMASK, DL, PtrVT, Ops);
211 return std::make_pair(End, Chain);
212}
213
215 SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Dest,
216 SDValue Src, MachinePointerInfo DestPtrInfo, MachinePointerInfo SrcPtrInfo,
217 bool isStpcpy) const {
218 SDVTList VTs = DAG.getVTList(Dest.getValueType(), MVT::Other);
219 SDValue EndDest = DAG.getNode(SystemZISD::STPCPY, DL, VTs, Chain, Dest, Src,
220 DAG.getConstant(0, DL, MVT::i32));
221 return std::make_pair(isStpcpy ? EndDest : Dest, EndDest.getValue(1));
222}
223
225 SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src1,
226 SDValue Src2, MachinePointerInfo Op1PtrInfo,
227 MachinePointerInfo Op2PtrInfo) const {
228 SDVTList VTs = DAG.getVTList(Src1.getValueType(), MVT::i32, MVT::Other);
229 // Swap operands to invert CC == 1 vs. CC == 2 cases.
230 SDValue Unused = DAG.getNode(SystemZISD::STRCMP, DL, VTs, Chain, Src2, Src1,
231 DAG.getConstant(0, DL, MVT::i32));
232 SDValue CCReg = Unused.getValue(1);
233 Chain = Unused.getValue(2);
234 return std::make_pair(addIPMSequence(DL, CCReg, DAG), Chain);
235}
236
237// Search from Src for a null character, stopping once Src reaches Limit.
238// Return a pair of values, the first being the number of nonnull characters
239// and the second being the out chain.
240//
241// This can be used for strlen by setting Limit to 0.
242static std::pair<SDValue, SDValue> getBoundedStrlen(SelectionDAG &DAG,
243 const SDLoc &DL,
244 SDValue Chain, SDValue Src,
245 SDValue Limit) {
246 EVT PtrVT = Src.getValueType();
247 SDVTList VTs = DAG.getVTList(PtrVT, MVT::i32, MVT::Other);
249 Limit, Src, DAG.getConstant(0, DL, MVT::i32));
250 Chain = End.getValue(2);
251 SDValue Len = DAG.getNode(ISD::SUB, DL, PtrVT, End, Src);
252 return std::make_pair(Len, Chain);
253}
254
256 SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src,
257 MachinePointerInfo SrcPtrInfo) const {
258 EVT PtrVT = Src.getValueType();
259 return getBoundedStrlen(DAG, DL, Chain, Src, DAG.getConstant(0, DL, PtrVT));
260}
261
263 SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src,
264 SDValue MaxLength, MachinePointerInfo SrcPtrInfo) const {
265 EVT PtrVT = Src.getValueType();
266 MaxLength = DAG.getZExtOrTrunc(MaxLength, DL, PtrVT);
267 SDValue Limit = DAG.getNode(ISD::ADD, DL, PtrVT, Src, MaxLength);
268 return getBoundedStrlen(DAG, DL, Chain, Src, Limit);
269}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
uint64_t Size
bool End
Definition: ELF_riscv.cpp:480
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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 an Operation in the Expression.
static MVT getIntegerVT(unsigned BitWidth)
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.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
Definition: SelectionDAG.h:228
SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
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.
SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
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...
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)
Definition: SelectionDAG.h:698
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.
Definition: SmallVector.h:1196
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 > EmitTargetCodeForStrlen(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src, MachinePointerInfo SrcPtrInfo) const override
std::pair< SDValue, SDValue > EmitTargetCodeForStrcmp(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src1, SDValue Src2, MachinePointerInfo Op1PtrInfo, MachinePointerInfo Op2PtrInfo) const override
Emit target-specific code that performs a strcmp, in cases where that is faster than a libcall.
std::pair< SDValue, SDValue > EmitTargetCodeForStrnlen(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src, SDValue MaxLength, MachinePointerInfo SrcPtrInfo) 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 override
Emit target-specific code that performs a strcpy or stpcpy, in cases where that is faster than a libc...
SDValue EmitTargetCodeForMemcpy(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool IsVolatile, bool AlwaysInline, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const override
Emit target-specific code that performs a memcpy.
std::pair< SDValue, SDValue > EmitTargetCodeForMemcmp(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src1, SDValue Src2, SDValue Size, MachinePointerInfo Op1PtrInfo, MachinePointerInfo Op2PtrInfo) const override
Emit target-specific code that performs a memcmp/bcmp, in cases where that is faster than a libcall.
@ ADD
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:246
@ SHL
Shift and rotation operations.
Definition: ISDOpcodes.h:735
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:709
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition: ISDOpcodes.h:52
const unsigned CCMASK_SRST
Definition: SystemZ.h:74
const unsigned CCMASK_SRST_FOUND
Definition: SystemZ.h:72
const unsigned IPM_CC
Definition: SystemZ.h:112
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Length
Definition: DWP.cpp:480
int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition: bit.h:385
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
Definition: bit.h:327
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.