xref: /freebsd/contrib/llvm-project/llvm/lib/Target/VE/VECustomDAG.h (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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())
MaskVETargetMasks139       : Mask(Mask), AVL(AVL) {}
140 };
141 
142 class VECustomDAG {
143   SelectionDAG &DAG;
144   SDLoc DL;
145 
146 public:
getDAG()147   SelectionDAG *getDAG() const { return &DAG; }
148 
VECustomDAG(SelectionDAG & DAG,SDLoc DL)149   VECustomDAG(SelectionDAG &DAG, SDLoc DL) : DAG(DAG), DL(DL) {}
150 
VECustomDAG(SelectionDAG & DAG,SDValue WhereOp)151   VECustomDAG(SelectionDAG &DAG, SDValue WhereOp) : DAG(DAG), DL(WhereOp) {}
152 
VECustomDAG(SelectionDAG & DAG,const SDNode * WhereN)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(OC, DL, VTL, 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(OC, DL, ResVT, 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(OC, DL, ResVT, OpV);
175     if (Flags)
176       N->setFlags(*Flags);
177     return N;
178   }
179 
getUNDEF(EVT VT)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 
getMergeValues(ArrayRef<SDValue> Values)194   SDValue getMergeValues(ArrayRef<SDValue> Values) const {
195     return DAG.getMergeValues(Values, 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;
getVectorVT(EVT ElemVT,unsigned NumElems)216   EVT getVectorVT(EVT ElemVT, unsigned NumElems) const {
217     return EVT::getVectorVT(*DAG.getContext(), ElemVT, NumElems);
218   }
219 };
220 
221 } // namespace llvm
222 
223 #endif // LLVM_LIB_TARGET_VE_VECUSTOMDAG_H
224