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