xref: /freebsd/contrib/llvm-project/llvm/lib/Target/VE/VECustomDAG.h (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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 
24*bdd1243dSDimitry Andric std::optional<unsigned> getVVPOpcode(unsigned Opcode);
2504eeddc0SDimitry Andric 
2681ad6265SDimitry Andric bool isVVPUnaryOp(unsigned Opcode);
2704eeddc0SDimitry Andric bool isVVPBinaryOp(unsigned Opcode);
2881ad6265SDimitry Andric bool isVVPReductionOp(unsigned Opcode);
2981ad6265SDimitry Andric 
3081ad6265SDimitry Andric MVT splitVectorType(MVT VT);
3104eeddc0SDimitry Andric 
3204eeddc0SDimitry Andric bool isPackedVectorType(EVT SomeVT);
3304eeddc0SDimitry Andric 
3481ad6265SDimitry Andric bool isMaskType(EVT SomeVT);
3581ad6265SDimitry Andric 
3681ad6265SDimitry Andric bool isMaskArithmetic(SDValue Op);
3781ad6265SDimitry Andric 
3881ad6265SDimitry Andric bool isVVPOrVEC(unsigned);
3981ad6265SDimitry Andric 
4081ad6265SDimitry Andric bool supportsPackedMode(unsigned Opcode, EVT IdiomVT);
4181ad6265SDimitry Andric 
4281ad6265SDimitry Andric bool isPackingSupportOpcode(unsigned Opc);
4381ad6265SDimitry Andric 
4481ad6265SDimitry Andric bool maySafelyIgnoreMask(SDValue Op);
4581ad6265SDimitry Andric 
4681ad6265SDimitry Andric /// The VE backend uses a two-staged process to lower and legalize vector
4781ad6265SDimitry Andric /// instructions:
4881ad6265SDimitry Andric //
4981ad6265SDimitry Andric /// 1. VP and standard vector SDNodes are lowered to SDNodes of the VVP_* layer.
5081ad6265SDimitry Andric //
5181ad6265SDimitry Andric //     All VVP nodes have a mask and an Active Vector Length (AVL) parameter.
5281ad6265SDimitry Andric //     The AVL parameters refers to the element position in the vector the VVP
5381ad6265SDimitry Andric //     node operates on.
5481ad6265SDimitry Andric //
5581ad6265SDimitry Andric //
5681ad6265SDimitry Andric //  2. The VVP SDNodes are legalized. The AVL in a legal VVP node refers to
5781ad6265SDimitry Andric //     chunks of 64bit. We track this by wrapping the AVL in a LEGALAVL node.
5881ad6265SDimitry Andric //
5981ad6265SDimitry Andric //     The AVL mechanism in the VE architecture always refers to chunks of
6081ad6265SDimitry Andric //     64bit, regardless of the actual element type vector instructions are
6181ad6265SDimitry Andric //     operating on. For vector types v256.32 or v256.64 nothing needs to be
6281ad6265SDimitry Andric //     legalized since each element occupies a 64bit chunk - there is no
6381ad6265SDimitry Andric //     difference between counting 64bit chunks or element positions. However,
6481ad6265SDimitry Andric //     all vector types with > 256 elements store more than one logical element
6581ad6265SDimitry Andric //     per 64bit chunk and need to be transformed.
6681ad6265SDimitry Andric //     However legalization is performed, the resulting legal VVP SDNodes will
6781ad6265SDimitry Andric //     have a LEGALAVL node as their AVL operand. The LEGALAVL nodes wraps
6881ad6265SDimitry Andric //     around an AVL that refers to 64 bit chunks just as the architecture
6981ad6265SDimitry Andric //     demands - that is, the wrapped AVL is the correct setting for the VL
7081ad6265SDimitry Andric //     register for this VVP operation to get the desired behavior.
7181ad6265SDimitry Andric //
7281ad6265SDimitry Andric /// AVL Functions {
7381ad6265SDimitry Andric // The AVL operand position of this node.
74*bdd1243dSDimitry Andric std::optional<int> getAVLPos(unsigned);
7581ad6265SDimitry Andric 
7681ad6265SDimitry Andric // Whether this is a LEGALAVL node.
7781ad6265SDimitry Andric bool isLegalAVL(SDValue AVL);
7881ad6265SDimitry Andric 
7981ad6265SDimitry Andric // The AVL operand of this node.
8081ad6265SDimitry Andric SDValue getNodeAVL(SDValue);
8181ad6265SDimitry Andric 
8281ad6265SDimitry Andric // Mask position of this node.
83*bdd1243dSDimitry Andric std::optional<int> getMaskPos(unsigned);
8481ad6265SDimitry Andric 
8581ad6265SDimitry Andric SDValue getNodeMask(SDValue);
8681ad6265SDimitry Andric 
8781ad6265SDimitry Andric // Return the AVL operand of this node. If it is a LEGALAVL node, unwrap it.
8881ad6265SDimitry Andric // Return with the boolean whether unwrapping happened.
8981ad6265SDimitry Andric std::pair<SDValue, bool> getAnnotatedNodeAVL(SDValue);
9081ad6265SDimitry Andric 
9181ad6265SDimitry Andric /// } AVL Functions
9281ad6265SDimitry Andric 
9381ad6265SDimitry Andric /// Node Properties {
9481ad6265SDimitry Andric 
95*bdd1243dSDimitry Andric std::optional<EVT> getIdiomaticVectorType(SDNode *Op);
9681ad6265SDimitry Andric 
9781ad6265SDimitry Andric SDValue getLoadStoreStride(SDValue Op, VECustomDAG &CDAG);
9881ad6265SDimitry Andric 
9981ad6265SDimitry Andric SDValue getMemoryPtr(SDValue Op);
10081ad6265SDimitry Andric 
10181ad6265SDimitry Andric SDValue getNodeChain(SDValue Op);
10281ad6265SDimitry Andric 
10381ad6265SDimitry Andric SDValue getStoredValue(SDValue Op);
10481ad6265SDimitry Andric 
10581ad6265SDimitry Andric SDValue getNodePassthru(SDValue Op);
10681ad6265SDimitry Andric 
10781ad6265SDimitry Andric SDValue getGatherScatterIndex(SDValue Op);
10881ad6265SDimitry Andric 
10981ad6265SDimitry Andric SDValue getGatherScatterScale(SDValue Op);
11081ad6265SDimitry Andric 
11181ad6265SDimitry Andric unsigned getScalarReductionOpcode(unsigned VVPOC, bool IsMask);
11281ad6265SDimitry Andric 
11381ad6265SDimitry Andric // Whether this VP_REDUCE_*/ VECREDUCE_*/VVP_REDUCE_* SDNode has a start
11481ad6265SDimitry Andric // parameter.
11581ad6265SDimitry Andric bool hasReductionStartParam(unsigned VVPOC);
11681ad6265SDimitry Andric 
11781ad6265SDimitry Andric /// } Node Properties
11881ad6265SDimitry Andric 
11981ad6265SDimitry Andric enum class Packing {
12081ad6265SDimitry Andric   Normal = 0, // 256 element standard mode.
12181ad6265SDimitry Andric   Dense = 1   // 512 element packed mode.
12281ad6265SDimitry Andric };
12381ad6265SDimitry Andric 
12481ad6265SDimitry Andric // Get the vector or mask register type for this packing and element type.
12581ad6265SDimitry Andric MVT getLegalVectorType(Packing P, MVT ElemVT);
12681ad6265SDimitry Andric 
12781ad6265SDimitry Andric // Whether this type belongs to a packed mask or vector register.
12881ad6265SDimitry Andric Packing getTypePacking(EVT);
12981ad6265SDimitry Andric 
13081ad6265SDimitry Andric enum class PackElem : int8_t {
13181ad6265SDimitry Andric   Lo = 0, // Integer (63, 32]
13281ad6265SDimitry Andric   Hi = 1  // Float   (32,  0]
13381ad6265SDimitry Andric };
13481ad6265SDimitry Andric 
13581ad6265SDimitry Andric struct VETargetMasks {
13681ad6265SDimitry Andric   SDValue Mask;
13781ad6265SDimitry Andric   SDValue AVL;
13881ad6265SDimitry Andric   VETargetMasks(SDValue Mask = SDValue(), SDValue AVL = SDValue())
MaskVETargetMasks13981ad6265SDimitry Andric       : Mask(Mask), AVL(AVL) {}
14081ad6265SDimitry Andric };
14181ad6265SDimitry Andric 
14204eeddc0SDimitry Andric class VECustomDAG {
14304eeddc0SDimitry Andric   SelectionDAG &DAG;
14404eeddc0SDimitry Andric   SDLoc DL;
14504eeddc0SDimitry Andric 
14604eeddc0SDimitry Andric public:
getDAG()14704eeddc0SDimitry Andric   SelectionDAG *getDAG() const { return &DAG; }
14804eeddc0SDimitry Andric 
VECustomDAG(SelectionDAG & DAG,SDLoc DL)14904eeddc0SDimitry Andric   VECustomDAG(SelectionDAG &DAG, SDLoc DL) : DAG(DAG), DL(DL) {}
15004eeddc0SDimitry Andric 
VECustomDAG(SelectionDAG & DAG,SDValue WhereOp)15104eeddc0SDimitry Andric   VECustomDAG(SelectionDAG &DAG, SDValue WhereOp) : DAG(DAG), DL(WhereOp) {}
15204eeddc0SDimitry Andric 
VECustomDAG(SelectionDAG & DAG,const SDNode * WhereN)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,
157*bdd1243dSDimitry Andric                   std::optional<SDNodeFlags> Flags = std::nullopt) 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,
165*bdd1243dSDimitry Andric                   std::optional<SDNodeFlags> Flags = std::nullopt) 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,
173*bdd1243dSDimitry Andric                   std::optional<SDNodeFlags> Flags = std::nullopt) 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 
getUNDEF(EVT VT)18004eeddc0SDimitry Andric   SDValue getUNDEF(EVT VT) const { return DAG.getUNDEF(VT); }
18104eeddc0SDimitry Andric   /// } getNode
18204eeddc0SDimitry Andric 
18381ad6265SDimitry Andric   /// Legalizing getNode {
18481ad6265SDimitry Andric   SDValue getLegalReductionOpVVP(unsigned VVPOpcode, EVT ResVT, SDValue StartV,
18581ad6265SDimitry Andric                                  SDValue VectorV, SDValue Mask, SDValue AVL,
18681ad6265SDimitry Andric                                  SDNodeFlags Flags) const;
18781ad6265SDimitry Andric   /// } Legalizing getNode
18881ad6265SDimitry Andric 
18981ad6265SDimitry Andric   /// Packing {
19081ad6265SDimitry Andric   SDValue getUnpack(EVT DestVT, SDValue Vec, PackElem Part, SDValue AVL) const;
19181ad6265SDimitry Andric   SDValue getPack(EVT DestVT, SDValue LoVec, SDValue HiVec, SDValue AVL) const;
19281ad6265SDimitry Andric   /// } Packing
19381ad6265SDimitry Andric 
getMergeValues(ArrayRef<SDValue> Values)19481ad6265SDimitry Andric   SDValue getMergeValues(ArrayRef<SDValue> Values) const {
19581ad6265SDimitry Andric     return DAG.getMergeValues(Values, DL);
19681ad6265SDimitry Andric   }
19781ad6265SDimitry Andric 
19804eeddc0SDimitry Andric   SDValue getConstant(uint64_t Val, EVT VT, bool IsTarget = false,
19904eeddc0SDimitry Andric                       bool IsOpaque = false) const;
20004eeddc0SDimitry Andric 
20181ad6265SDimitry Andric   SDValue getConstantMask(Packing Packing, bool AllTrue) const;
20281ad6265SDimitry Andric   SDValue getMaskBroadcast(EVT ResultVT, SDValue Scalar, SDValue AVL) const;
20304eeddc0SDimitry Andric   SDValue getBroadcast(EVT ResultVT, SDValue Scalar, SDValue AVL) const;
20481ad6265SDimitry Andric 
20581ad6265SDimitry Andric   // Wrap AVL in a LEGALAVL node (unless it is one already).
20681ad6265SDimitry Andric   SDValue annotateLegalAVL(SDValue AVL) const;
20781ad6265SDimitry Andric   VETargetMasks getTargetSplitMask(SDValue RawMask, SDValue RawAVL,
20881ad6265SDimitry Andric                                    PackElem Part) const;
20981ad6265SDimitry Andric 
21081ad6265SDimitry Andric   // Splitting support
21181ad6265SDimitry Andric   SDValue getSplitPtrOffset(SDValue Ptr, SDValue ByteStride,
21281ad6265SDimitry Andric                             PackElem Part) const;
21381ad6265SDimitry Andric   SDValue getSplitPtrStride(SDValue PackStride) const;
21481ad6265SDimitry Andric   SDValue getGatherScatterAddress(SDValue BasePtr, SDValue Scale, SDValue Index,
21581ad6265SDimitry Andric                                   SDValue Mask, SDValue AVL) const;
getVectorVT(EVT ElemVT,unsigned NumElems)21681ad6265SDimitry Andric   EVT getVectorVT(EVT ElemVT, unsigned NumElems) const {
21781ad6265SDimitry Andric     return EVT::getVectorVT(*DAG.getContext(), ElemVT, NumElems);
21881ad6265SDimitry Andric   }
21904eeddc0SDimitry Andric };
22004eeddc0SDimitry Andric 
22104eeddc0SDimitry Andric } // namespace llvm
22204eeddc0SDimitry Andric 
22304eeddc0SDimitry Andric #endif // LLVM_LIB_TARGET_VE_VECUSTOMDAG_H
224