1//===------------ VECustomDAG.h - VE Custom DAG Nodes -----------*- C++ -*-===//
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 defines the helper functions that VE uses to lower LLVM code into a
10// selection DAG. For example, hiding SDLoc, and easy to use SDNodeFlags.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_LIB_TARGET_VE_VECUSTOMDAG_H
15#define LLVM_LIB_TARGET_VE_VECUSTOMDAG_H
16
17#include "VE.h"
18#include "VEISelLowering.h"
19#include "llvm/CodeGen/SelectionDAG.h"
20#include "llvm/CodeGen/TargetLowering.h"
21
22namespace llvm {
23
24std::optional<unsigned> getVVPOpcode(unsigned Opcode);
25
26bool isVVPUnaryOp(unsigned Opcode);
27bool isVVPBinaryOp(unsigned Opcode);
28bool isVVPReductionOp(unsigned Opcode);
29
30MVT splitVectorType(MVT VT);
31
32bool isPackedVectorType(EVT SomeVT);
33
34bool isMaskType(EVT SomeVT);
35
36bool isMaskArithmetic(SDValue Op);
37
38bool isVVPOrVEC(unsigned);
39
40bool supportsPackedMode(unsigned Opcode, EVT IdiomVT);
41
42bool isPackingSupportOpcode(unsigned Opc);
43
44bool maySafelyIgnoreMask(SDValue Op);
45
46/// The VE backend uses a two-staged process to lower and legalize vector
47/// instructions:
48//
49/// 1. VP and standard vector SDNodes are lowered to SDNodes of the VVP_* layer.
50//
51// All VVP nodes have a mask and an Active Vector Length (AVL) parameter.
52// The AVL parameters refers to the element position in the vector the VVP
53// node operates on.
54//
55//
56// 2. The VVP SDNodes are legalized. The AVL in a legal VVP node refers to
57// chunks of 64bit. We track this by wrapping the AVL in a LEGALAVL node.
58//
59// The AVL mechanism in the VE architecture always refers to chunks of
60// 64bit, regardless of the actual element type vector instructions are
61// operating on. For vector types v256.32 or v256.64 nothing needs to be
62// legalized since each element occupies a 64bit chunk - there is no
63// difference between counting 64bit chunks or element positions. However,
64// all vector types with > 256 elements store more than one logical element
65// per 64bit chunk and need to be transformed.
66// However legalization is performed, the resulting legal VVP SDNodes will
67// have a LEGALAVL node as their AVL operand. The LEGALAVL nodes wraps
68// around an AVL that refers to 64 bit chunks just as the architecture
69// demands - that is, the wrapped AVL is the correct setting for the VL
70// register for this VVP operation to get the desired behavior.
71//
72/// AVL Functions {
73// The AVL operand position of this node.
74std::optional<int> getAVLPos(unsigned);
75
76// Whether this is a LEGALAVL node.
77bool isLegalAVL(SDValue AVL);
78
79// The AVL operand of this node.
80SDValue getNodeAVL(SDValue);
81
82// Mask position of this node.
83std::optional<int> getMaskPos(unsigned);
84
85SDValue getNodeMask(SDValue);
86
87// Return the AVL operand of this node. If it is a LEGALAVL node, unwrap it.
88// Return with the boolean whether unwrapping happened.
89std::pair<SDValue, bool> getAnnotatedNodeAVL(SDValue);
90
91/// } AVL Functions
92
93/// Node Properties {
94
95std::optional<EVT> getIdiomaticVectorType(SDNode *Op);
96
97SDValue getLoadStoreStride(SDValue Op, VECustomDAG &CDAG);
98
99SDValue getMemoryPtr(SDValue Op);
100
101SDValue getNodeChain(SDValue Op);
102
103SDValue getStoredValue(SDValue Op);
104
105SDValue getNodePassthru(SDValue Op);
106
107SDValue getGatherScatterIndex(SDValue Op);
108
109SDValue getGatherScatterScale(SDValue Op);
110
111unsigned getScalarReductionOpcode(unsigned VVPOC, bool IsMask);
112
113// Whether this VP_REDUCE_*/ VECREDUCE_*/VVP_REDUCE_* SDNode has a start
114// parameter.
115bool hasReductionStartParam(unsigned VVPOC);
116
117/// } Node Properties
118
119enum class Packing {
120 Normal = 0, // 256 element standard mode.
121 Dense = 1 // 512 element packed mode.
122};
123
124// Get the vector or mask register type for this packing and element type.
125MVT getLegalVectorType(Packing P, MVT ElemVT);
126
127// Whether this type belongs to a packed mask or vector register.
128Packing getTypePacking(EVT);
129
130enum class PackElem : int8_t {
131 Lo = 0, // Integer (63, 32]
132 Hi = 1 // Float (32, 0]
133};
134
135struct VETargetMasks {
136 SDValue Mask;
137 SDValue AVL;
138 VETargetMasks(SDValue Mask = SDValue(), SDValue AVL = SDValue())
139 : Mask(Mask), AVL(AVL) {}
140};
141
142class VECustomDAG {
143 SelectionDAG &DAG;
144 SDLoc DL;
145
146public:
147 SelectionDAG *getDAG() const { return &DAG; }
148
149 VECustomDAG(SelectionDAG &DAG, SDLoc DL) : DAG(DAG), DL(DL) {}
150
151 VECustomDAG(SelectionDAG &DAG, SDValue WhereOp) : DAG(DAG), DL(WhereOp) {}
152
153 VECustomDAG(SelectionDAG &DAG, const SDNode *WhereN) : DAG(DAG), DL(WhereN) {}
154
155 /// getNode {
156 SDValue getNode(unsigned OC, SDVTList VTL, ArrayRef<SDValue> OpV,
157 std::optional<SDNodeFlags> Flags = std::nullopt) const {
158 auto N = DAG.getNode(Opcode: OC, DL, VTList: VTL, Ops: OpV);
159 if (Flags)
160 N->setFlags(*Flags);
161 return N;
162 }
163
164 SDValue getNode(unsigned OC, ArrayRef<EVT> ResVT, ArrayRef<SDValue> OpV,
165 std::optional<SDNodeFlags> Flags = std::nullopt) const {
166 auto N = DAG.getNode(Opcode: OC, DL, ResultTys: ResVT, Ops: OpV);
167 if (Flags)
168 N->setFlags(*Flags);
169 return N;
170 }
171
172 SDValue getNode(unsigned OC, EVT ResVT, ArrayRef<SDValue> OpV,
173 std::optional<SDNodeFlags> Flags = std::nullopt) const {
174 auto N = DAG.getNode(Opcode: OC, DL, VT: ResVT, Ops: OpV);
175 if (Flags)
176 N->setFlags(*Flags);
177 return N;
178 }
179
180 SDValue getUNDEF(EVT VT) const { return DAG.getUNDEF(VT); }
181 /// } getNode
182
183 /// Legalizing getNode {
184 SDValue getLegalReductionOpVVP(unsigned VVPOpcode, EVT ResVT, SDValue StartV,
185 SDValue VectorV, SDValue Mask, SDValue AVL,
186 SDNodeFlags Flags) const;
187 /// } Legalizing getNode
188
189 /// Packing {
190 SDValue getUnpack(EVT DestVT, SDValue Vec, PackElem Part, SDValue AVL) const;
191 SDValue getPack(EVT DestVT, SDValue LoVec, SDValue HiVec, SDValue AVL) const;
192 /// } Packing
193
194 SDValue getMergeValues(ArrayRef<SDValue> Values) const {
195 return DAG.getMergeValues(Ops: Values, dl: DL);
196 }
197
198 SDValue getConstant(uint64_t Val, EVT VT, bool IsTarget = false,
199 bool IsOpaque = false) const;
200
201 SDValue getConstantMask(Packing Packing, bool AllTrue) const;
202 SDValue getMaskBroadcast(EVT ResultVT, SDValue Scalar, SDValue AVL) const;
203 SDValue getBroadcast(EVT ResultVT, SDValue Scalar, SDValue AVL) const;
204
205 // Wrap AVL in a LEGALAVL node (unless it is one already).
206 SDValue annotateLegalAVL(SDValue AVL) const;
207 VETargetMasks getTargetSplitMask(SDValue RawMask, SDValue RawAVL,
208 PackElem Part) const;
209
210 // Splitting support
211 SDValue getSplitPtrOffset(SDValue Ptr, SDValue ByteStride,
212 PackElem Part) const;
213 SDValue getSplitPtrStride(SDValue PackStride) const;
214 SDValue getGatherScatterAddress(SDValue BasePtr, SDValue Scale, SDValue Index,
215 SDValue Mask, SDValue AVL) const;
216 EVT getVectorVT(EVT ElemVT, unsigned NumElems) const {
217 return EVT::getVectorVT(Context&: *DAG.getContext(), VT: ElemVT, NumElements: NumElems);
218 }
219};
220
221} // namespace llvm
222
223#endif // LLVM_LIB_TARGET_VE_VECUSTOMDAG_H
224