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