xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/VE/VECustomDAG.h (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
104eeddc0SDimitry Andric //===------------ VECustomDAG.h - VE Custom DAG Nodes -----------*- C++ -*-===//
204eeddc0SDimitry Andric //
304eeddc0SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
404eeddc0SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
504eeddc0SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
604eeddc0SDimitry Andric //
704eeddc0SDimitry Andric //===----------------------------------------------------------------------===//
804eeddc0SDimitry Andric //
904eeddc0SDimitry Andric // This file defines the helper functions that VE uses to lower LLVM code into a
1004eeddc0SDimitry Andric // selection DAG.  For example, hiding SDLoc, and easy to use SDNodeFlags.
1104eeddc0SDimitry Andric //
1204eeddc0SDimitry Andric //===----------------------------------------------------------------------===//
1304eeddc0SDimitry Andric 
1404eeddc0SDimitry Andric #ifndef LLVM_LIB_TARGET_VE_VECUSTOMDAG_H
1504eeddc0SDimitry Andric #define LLVM_LIB_TARGET_VE_VECUSTOMDAG_H
1604eeddc0SDimitry Andric 
1704eeddc0SDimitry Andric #include "VE.h"
1804eeddc0SDimitry Andric #include "VEISelLowering.h"
1904eeddc0SDimitry Andric #include "llvm/CodeGen/SelectionDAG.h"
2004eeddc0SDimitry Andric #include "llvm/CodeGen/TargetLowering.h"
2104eeddc0SDimitry Andric 
2204eeddc0SDimitry Andric namespace llvm {
2304eeddc0SDimitry Andric 
2404eeddc0SDimitry Andric Optional<unsigned> getVVPOpcode(unsigned Opcode);
2504eeddc0SDimitry Andric 
26*81ad6265SDimitry Andric bool isVVPUnaryOp(unsigned Opcode);
2704eeddc0SDimitry Andric bool isVVPBinaryOp(unsigned Opcode);
28*81ad6265SDimitry Andric bool isVVPReductionOp(unsigned Opcode);
29*81ad6265SDimitry Andric 
30*81ad6265SDimitry Andric MVT splitVectorType(MVT VT);
3104eeddc0SDimitry Andric 
3204eeddc0SDimitry Andric bool isPackedVectorType(EVT SomeVT);
3304eeddc0SDimitry Andric 
34*81ad6265SDimitry Andric bool isMaskType(EVT SomeVT);
35*81ad6265SDimitry Andric 
36*81ad6265SDimitry Andric bool isMaskArithmetic(SDValue Op);
37*81ad6265SDimitry Andric 
38*81ad6265SDimitry Andric bool isVVPOrVEC(unsigned);
39*81ad6265SDimitry Andric 
40*81ad6265SDimitry Andric bool supportsPackedMode(unsigned Opcode, EVT IdiomVT);
41*81ad6265SDimitry Andric 
42*81ad6265SDimitry Andric bool isPackingSupportOpcode(unsigned Opc);
43*81ad6265SDimitry Andric 
44*81ad6265SDimitry Andric bool maySafelyIgnoreMask(SDValue Op);
45*81ad6265SDimitry Andric 
46*81ad6265SDimitry Andric /// The VE backend uses a two-staged process to lower and legalize vector
47*81ad6265SDimitry Andric /// instructions:
48*81ad6265SDimitry Andric //
49*81ad6265SDimitry Andric /// 1. VP and standard vector SDNodes are lowered to SDNodes of the VVP_* layer.
50*81ad6265SDimitry Andric //
51*81ad6265SDimitry Andric //     All VVP nodes have a mask and an Active Vector Length (AVL) parameter.
52*81ad6265SDimitry Andric //     The AVL parameters refers to the element position in the vector the VVP
53*81ad6265SDimitry Andric //     node operates on.
54*81ad6265SDimitry Andric //
55*81ad6265SDimitry Andric //
56*81ad6265SDimitry Andric //  2. The VVP SDNodes are legalized. The AVL in a legal VVP node refers to
57*81ad6265SDimitry Andric //     chunks of 64bit. We track this by wrapping the AVL in a LEGALAVL node.
58*81ad6265SDimitry Andric //
59*81ad6265SDimitry Andric //     The AVL mechanism in the VE architecture always refers to chunks of
60*81ad6265SDimitry Andric //     64bit, regardless of the actual element type vector instructions are
61*81ad6265SDimitry Andric //     operating on. For vector types v256.32 or v256.64 nothing needs to be
62*81ad6265SDimitry Andric //     legalized since each element occupies a 64bit chunk - there is no
63*81ad6265SDimitry Andric //     difference between counting 64bit chunks or element positions. However,
64*81ad6265SDimitry Andric //     all vector types with > 256 elements store more than one logical element
65*81ad6265SDimitry Andric //     per 64bit chunk and need to be transformed.
66*81ad6265SDimitry Andric //     However legalization is performed, the resulting legal VVP SDNodes will
67*81ad6265SDimitry Andric //     have a LEGALAVL node as their AVL operand. The LEGALAVL nodes wraps
68*81ad6265SDimitry Andric //     around an AVL that refers to 64 bit chunks just as the architecture
69*81ad6265SDimitry Andric //     demands - that is, the wrapped AVL is the correct setting for the VL
70*81ad6265SDimitry Andric //     register for this VVP operation to get the desired behavior.
71*81ad6265SDimitry Andric //
72*81ad6265SDimitry Andric /// AVL Functions {
73*81ad6265SDimitry Andric // The AVL operand position of this node.
74*81ad6265SDimitry Andric Optional<int> getAVLPos(unsigned);
75*81ad6265SDimitry Andric 
76*81ad6265SDimitry Andric // Whether this is a LEGALAVL node.
77*81ad6265SDimitry Andric bool isLegalAVL(SDValue AVL);
78*81ad6265SDimitry Andric 
79*81ad6265SDimitry Andric // The AVL operand of this node.
80*81ad6265SDimitry Andric SDValue getNodeAVL(SDValue);
81*81ad6265SDimitry Andric 
82*81ad6265SDimitry Andric // Mask position of this node.
83*81ad6265SDimitry Andric Optional<int> getMaskPos(unsigned);
84*81ad6265SDimitry Andric 
85*81ad6265SDimitry Andric SDValue getNodeMask(SDValue);
86*81ad6265SDimitry Andric 
87*81ad6265SDimitry Andric // Return the AVL operand of this node. If it is a LEGALAVL node, unwrap it.
88*81ad6265SDimitry Andric // Return with the boolean whether unwrapping happened.
89*81ad6265SDimitry Andric std::pair<SDValue, bool> getAnnotatedNodeAVL(SDValue);
90*81ad6265SDimitry Andric 
91*81ad6265SDimitry Andric /// } AVL Functions
92*81ad6265SDimitry Andric 
93*81ad6265SDimitry Andric /// Node Properties {
94*81ad6265SDimitry Andric 
95*81ad6265SDimitry Andric Optional<EVT> getIdiomaticVectorType(SDNode *Op);
96*81ad6265SDimitry Andric 
97*81ad6265SDimitry Andric SDValue getLoadStoreStride(SDValue Op, VECustomDAG &CDAG);
98*81ad6265SDimitry Andric 
99*81ad6265SDimitry Andric SDValue getMemoryPtr(SDValue Op);
100*81ad6265SDimitry Andric 
101*81ad6265SDimitry Andric SDValue getNodeChain(SDValue Op);
102*81ad6265SDimitry Andric 
103*81ad6265SDimitry Andric SDValue getStoredValue(SDValue Op);
104*81ad6265SDimitry Andric 
105*81ad6265SDimitry Andric SDValue getNodePassthru(SDValue Op);
106*81ad6265SDimitry Andric 
107*81ad6265SDimitry Andric SDValue getGatherScatterIndex(SDValue Op);
108*81ad6265SDimitry Andric 
109*81ad6265SDimitry Andric SDValue getGatherScatterScale(SDValue Op);
110*81ad6265SDimitry Andric 
111*81ad6265SDimitry Andric unsigned getScalarReductionOpcode(unsigned VVPOC, bool IsMask);
112*81ad6265SDimitry Andric 
113*81ad6265SDimitry Andric // Whether this VP_REDUCE_*/ VECREDUCE_*/VVP_REDUCE_* SDNode has a start
114*81ad6265SDimitry Andric // parameter.
115*81ad6265SDimitry Andric bool hasReductionStartParam(unsigned VVPOC);
116*81ad6265SDimitry Andric 
117*81ad6265SDimitry Andric /// } Node Properties
118*81ad6265SDimitry Andric 
119*81ad6265SDimitry Andric enum class Packing {
120*81ad6265SDimitry Andric   Normal = 0, // 256 element standard mode.
121*81ad6265SDimitry Andric   Dense = 1   // 512 element packed mode.
122*81ad6265SDimitry Andric };
123*81ad6265SDimitry Andric 
124*81ad6265SDimitry Andric // Get the vector or mask register type for this packing and element type.
125*81ad6265SDimitry Andric MVT getLegalVectorType(Packing P, MVT ElemVT);
126*81ad6265SDimitry Andric 
127*81ad6265SDimitry Andric // Whether this type belongs to a packed mask or vector register.
128*81ad6265SDimitry Andric Packing getTypePacking(EVT);
129*81ad6265SDimitry Andric 
130*81ad6265SDimitry Andric enum class PackElem : int8_t {
131*81ad6265SDimitry Andric   Lo = 0, // Integer (63, 32]
132*81ad6265SDimitry Andric   Hi = 1  // Float   (32,  0]
133*81ad6265SDimitry Andric };
134*81ad6265SDimitry Andric 
135*81ad6265SDimitry Andric struct VETargetMasks {
136*81ad6265SDimitry Andric   SDValue Mask;
137*81ad6265SDimitry Andric   SDValue AVL;
138*81ad6265SDimitry Andric   VETargetMasks(SDValue Mask = SDValue(), SDValue AVL = SDValue())
139*81ad6265SDimitry Andric       : Mask(Mask), AVL(AVL) {}
140*81ad6265SDimitry Andric };
141*81ad6265SDimitry Andric 
14204eeddc0SDimitry Andric class VECustomDAG {
14304eeddc0SDimitry Andric   SelectionDAG &DAG;
14404eeddc0SDimitry Andric   SDLoc DL;
14504eeddc0SDimitry Andric 
14604eeddc0SDimitry Andric public:
14704eeddc0SDimitry Andric   SelectionDAG *getDAG() const { return &DAG; }
14804eeddc0SDimitry Andric 
14904eeddc0SDimitry Andric   VECustomDAG(SelectionDAG &DAG, SDLoc DL) : DAG(DAG), DL(DL) {}
15004eeddc0SDimitry Andric 
15104eeddc0SDimitry Andric   VECustomDAG(SelectionDAG &DAG, SDValue WhereOp) : DAG(DAG), DL(WhereOp) {}
15204eeddc0SDimitry Andric 
15304eeddc0SDimitry Andric   VECustomDAG(SelectionDAG &DAG, const SDNode *WhereN) : DAG(DAG), DL(WhereN) {}
15404eeddc0SDimitry Andric 
15504eeddc0SDimitry Andric   /// getNode {
15604eeddc0SDimitry Andric   SDValue getNode(unsigned OC, SDVTList VTL, ArrayRef<SDValue> OpV,
15704eeddc0SDimitry Andric                   Optional<SDNodeFlags> Flags = None) const {
15804eeddc0SDimitry Andric     auto N = DAG.getNode(OC, DL, VTL, OpV);
15904eeddc0SDimitry Andric     if (Flags)
16004eeddc0SDimitry Andric       N->setFlags(*Flags);
16104eeddc0SDimitry Andric     return N;
16204eeddc0SDimitry Andric   }
16304eeddc0SDimitry Andric 
16404eeddc0SDimitry Andric   SDValue getNode(unsigned OC, ArrayRef<EVT> ResVT, ArrayRef<SDValue> OpV,
16504eeddc0SDimitry Andric                   Optional<SDNodeFlags> Flags = None) const {
16604eeddc0SDimitry Andric     auto N = DAG.getNode(OC, DL, ResVT, OpV);
16704eeddc0SDimitry Andric     if (Flags)
16804eeddc0SDimitry Andric       N->setFlags(*Flags);
16904eeddc0SDimitry Andric     return N;
17004eeddc0SDimitry Andric   }
17104eeddc0SDimitry Andric 
17204eeddc0SDimitry Andric   SDValue getNode(unsigned OC, EVT ResVT, ArrayRef<SDValue> OpV,
17304eeddc0SDimitry Andric                   Optional<SDNodeFlags> Flags = None) const {
17404eeddc0SDimitry Andric     auto N = DAG.getNode(OC, DL, ResVT, OpV);
17504eeddc0SDimitry Andric     if (Flags)
17604eeddc0SDimitry Andric       N->setFlags(*Flags);
17704eeddc0SDimitry Andric     return N;
17804eeddc0SDimitry Andric   }
17904eeddc0SDimitry Andric 
18004eeddc0SDimitry Andric   SDValue getUNDEF(EVT VT) const { return DAG.getUNDEF(VT); }
18104eeddc0SDimitry Andric   /// } getNode
18204eeddc0SDimitry Andric 
183*81ad6265SDimitry Andric   /// Legalizing getNode {
184*81ad6265SDimitry Andric   SDValue getLegalReductionOpVVP(unsigned VVPOpcode, EVT ResVT, SDValue StartV,
185*81ad6265SDimitry Andric                                  SDValue VectorV, SDValue Mask, SDValue AVL,
186*81ad6265SDimitry Andric                                  SDNodeFlags Flags) const;
187*81ad6265SDimitry Andric   /// } Legalizing getNode
188*81ad6265SDimitry Andric 
189*81ad6265SDimitry Andric   /// Packing {
190*81ad6265SDimitry Andric   SDValue getUnpack(EVT DestVT, SDValue Vec, PackElem Part, SDValue AVL) const;
191*81ad6265SDimitry Andric   SDValue getPack(EVT DestVT, SDValue LoVec, SDValue HiVec, SDValue AVL) const;
192*81ad6265SDimitry Andric   /// } Packing
193*81ad6265SDimitry Andric 
194*81ad6265SDimitry Andric   SDValue getMergeValues(ArrayRef<SDValue> Values) const {
195*81ad6265SDimitry Andric     return DAG.getMergeValues(Values, DL);
196*81ad6265SDimitry Andric   }
197*81ad6265SDimitry Andric 
19804eeddc0SDimitry Andric   SDValue getConstant(uint64_t Val, EVT VT, bool IsTarget = false,
19904eeddc0SDimitry Andric                       bool IsOpaque = false) const;
20004eeddc0SDimitry Andric 
201*81ad6265SDimitry Andric   SDValue getConstantMask(Packing Packing, bool AllTrue) const;
202*81ad6265SDimitry Andric   SDValue getMaskBroadcast(EVT ResultVT, SDValue Scalar, SDValue AVL) const;
20304eeddc0SDimitry Andric   SDValue getBroadcast(EVT ResultVT, SDValue Scalar, SDValue AVL) const;
204*81ad6265SDimitry Andric 
205*81ad6265SDimitry Andric   // Wrap AVL in a LEGALAVL node (unless it is one already).
206*81ad6265SDimitry Andric   SDValue annotateLegalAVL(SDValue AVL) const;
207*81ad6265SDimitry Andric   VETargetMasks getTargetSplitMask(SDValue RawMask, SDValue RawAVL,
208*81ad6265SDimitry Andric                                    PackElem Part) const;
209*81ad6265SDimitry Andric 
210*81ad6265SDimitry Andric   // Splitting support
211*81ad6265SDimitry Andric   SDValue getSplitPtrOffset(SDValue Ptr, SDValue ByteStride,
212*81ad6265SDimitry Andric                             PackElem Part) const;
213*81ad6265SDimitry Andric   SDValue getSplitPtrStride(SDValue PackStride) const;
214*81ad6265SDimitry Andric   SDValue getGatherScatterAddress(SDValue BasePtr, SDValue Scale, SDValue Index,
215*81ad6265SDimitry Andric                                   SDValue Mask, SDValue AVL) const;
216*81ad6265SDimitry Andric   EVT getVectorVT(EVT ElemVT, unsigned NumElems) const {
217*81ad6265SDimitry Andric     return EVT::getVectorVT(*DAG.getContext(), ElemVT, NumElems);
218*81ad6265SDimitry Andric   }
21904eeddc0SDimitry Andric };
22004eeddc0SDimitry Andric 
22104eeddc0SDimitry Andric } // namespace llvm
22204eeddc0SDimitry Andric 
22304eeddc0SDimitry Andric #endif // LLVM_LIB_TARGET_VE_VECUSTOMDAG_H
224