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