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 | |
22 | namespace llvm { |
23 | |
24 | std::optional<unsigned> getVVPOpcode(unsigned Opcode); |
25 | |
26 | bool isVVPUnaryOp(unsigned Opcode); |
27 | bool isVVPBinaryOp(unsigned Opcode); |
28 | bool isVVPReductionOp(unsigned Opcode); |
29 | |
30 | MVT splitVectorType(MVT VT); |
31 | |
32 | bool isPackedVectorType(EVT SomeVT); |
33 | |
34 | bool isMaskType(EVT SomeVT); |
35 | |
36 | bool isMaskArithmetic(SDValue Op); |
37 | |
38 | bool isVVPOrVEC(unsigned); |
39 | |
40 | bool supportsPackedMode(unsigned Opcode, EVT IdiomVT); |
41 | |
42 | bool isPackingSupportOpcode(unsigned Opc); |
43 | |
44 | bool 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. |
74 | std::optional<int> getAVLPos(unsigned); |
75 | |
76 | // Whether this is a LEGALAVL node. |
77 | bool isLegalAVL(SDValue AVL); |
78 | |
79 | // The AVL operand of this node. |
80 | SDValue getNodeAVL(SDValue); |
81 | |
82 | // Mask position of this node. |
83 | std::optional<int> getMaskPos(unsigned); |
84 | |
85 | SDValue 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. |
89 | std::pair<SDValue, bool> getAnnotatedNodeAVL(SDValue); |
90 | |
91 | /// } AVL Functions |
92 | |
93 | /// Node Properties { |
94 | |
95 | std::optional<EVT> getIdiomaticVectorType(SDNode *Op); |
96 | |
97 | SDValue getLoadStoreStride(SDValue Op, VECustomDAG &CDAG); |
98 | |
99 | SDValue getMemoryPtr(SDValue Op); |
100 | |
101 | SDValue getNodeChain(SDValue Op); |
102 | |
103 | SDValue getStoredValue(SDValue Op); |
104 | |
105 | SDValue getNodePassthru(SDValue Op); |
106 | |
107 | SDValue getGatherScatterIndex(SDValue Op); |
108 | |
109 | SDValue getGatherScatterScale(SDValue Op); |
110 | |
111 | unsigned getScalarReductionOpcode(unsigned VVPOC, bool IsMask); |
112 | |
113 | // Whether this VP_REDUCE_*/ VECREDUCE_*/VVP_REDUCE_* SDNode has a start |
114 | // parameter. |
115 | bool hasReductionStartParam(unsigned VVPOC); |
116 | |
117 | /// } Node Properties |
118 | |
119 | enum 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. |
125 | MVT getLegalVectorType(Packing P, MVT ElemVT); |
126 | |
127 | // Whether this type belongs to a packed mask or vector register. |
128 | Packing getTypePacking(EVT); |
129 | |
130 | enum class PackElem : int8_t { |
131 | Lo = 0, // Integer (63, 32] |
132 | Hi = 1 // Float (32, 0] |
133 | }; |
134 | |
135 | struct VETargetMasks { |
136 | SDValue Mask; |
137 | SDValue AVL; |
138 | VETargetMasks(SDValue Mask = SDValue(), SDValue AVL = SDValue()) |
139 | : Mask(Mask), AVL(AVL) {} |
140 | }; |
141 | |
142 | class VECustomDAG { |
143 | SelectionDAG &DAG; |
144 | SDLoc DL; |
145 | |
146 | public: |
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 | |