11b09d0c4SSimon Moll //===-- VECustomDAG.h - VE Custom DAG Nodes ------------*- C++ -*-===// 21b09d0c4SSimon Moll // 31b09d0c4SSimon Moll // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41b09d0c4SSimon Moll // See https://llvm.org/LICENSE.txt for license information. 51b09d0c4SSimon Moll // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61b09d0c4SSimon Moll // 71b09d0c4SSimon Moll //===----------------------------------------------------------------------===// 81b09d0c4SSimon Moll // 91b09d0c4SSimon Moll // This file defines the interfaces that VE uses to lower LLVM code into a 101b09d0c4SSimon Moll // selection DAG. 111b09d0c4SSimon Moll // 121b09d0c4SSimon Moll //===----------------------------------------------------------------------===// 131b09d0c4SSimon Moll 141b09d0c4SSimon Moll #include "VECustomDAG.h" 151b09d0c4SSimon Moll 161b09d0c4SSimon Moll #ifndef DEBUG_TYPE 171b09d0c4SSimon Moll #define DEBUG_TYPE "vecustomdag" 181b09d0c4SSimon Moll #endif 191b09d0c4SSimon Moll 201b09d0c4SSimon Moll namespace llvm { 211b09d0c4SSimon Moll 225ceb0bc7SSimon Moll bool isPackedVectorType(EVT SomeVT) { 235ceb0bc7SSimon Moll if (!SomeVT.isVector()) 245ceb0bc7SSimon Moll return false; 255ceb0bc7SSimon Moll return SomeVT.getVectorNumElements() > StandardVectorWidth; 265ceb0bc7SSimon Moll } 275ceb0bc7SSimon Moll 284fd77129SSimon Moll MVT splitVectorType(MVT VT) { 294fd77129SSimon Moll if (!VT.isVector()) 304fd77129SSimon Moll return VT; 314fd77129SSimon Moll return MVT::getVectorVT(VT.getVectorElementType(), StandardVectorWidth); 324fd77129SSimon Moll } 334fd77129SSimon Moll 3453efbc15SSimon Moll MVT getLegalVectorType(Packing P, MVT ElemVT) { 3553efbc15SSimon Moll return MVT::getVectorVT(ElemVT, P == Packing::Normal ? StandardVectorWidth 3653efbc15SSimon Moll : PackedVectorWidth); 3753efbc15SSimon Moll } 3853efbc15SSimon Moll 3953efbc15SSimon Moll Packing getTypePacking(EVT VT) { 4053efbc15SSimon Moll assert(VT.isVector()); 4153efbc15SSimon Moll return isPackedVectorType(VT) ? Packing::Dense : Packing::Normal; 4253efbc15SSimon Moll } 4353efbc15SSimon Moll 4453efbc15SSimon Moll bool isMaskType(EVT SomeVT) { 4553efbc15SSimon Moll if (!SomeVT.isVector()) 4653efbc15SSimon Moll return false; 4753efbc15SSimon Moll return SomeVT.getVectorElementType() == MVT::i1; 4853efbc15SSimon Moll } 4953efbc15SSimon Moll 50cf964eb5SSimon Moll bool isMaskArithmetic(SDValue Op) { 51cf964eb5SSimon Moll switch (Op.getOpcode()) { 52cf964eb5SSimon Moll default: 53cf964eb5SSimon Moll return false; 54cf964eb5SSimon Moll case ISD::AND: 55cf964eb5SSimon Moll case ISD::XOR: 56cf964eb5SSimon Moll case ISD::OR: 57cf964eb5SSimon Moll return isMaskType(Op.getValueType()); 58cf964eb5SSimon Moll } 59cf964eb5SSimon Moll } 60cf964eb5SSimon Moll 617950010eSSimon Moll /// \returns the VVP_* SDNode opcode corresponsing to \p OC. 62b0df7040SFangrui Song std::optional<unsigned> getVVPOpcode(unsigned Opcode) { 637950010eSSimon Moll switch (Opcode) { 649ebaec46SSimon Moll case ISD::MLOAD: 659ebaec46SSimon Moll return VEISD::VVP_LOAD; 669ebaec46SSimon Moll case ISD::MSTORE: 679ebaec46SSimon Moll return VEISD::VVP_STORE; 687950010eSSimon Moll #define HANDLE_VP_TO_VVP(VPOPC, VVPNAME) \ 697950010eSSimon Moll case ISD::VPOPC: \ 707950010eSSimon Moll return VEISD::VVPNAME; 717950010eSSimon Moll #define ADD_VVP_OP(VVPNAME, SDNAME) \ 727950010eSSimon Moll case VEISD::VVPNAME: \ 737950010eSSimon Moll case ISD::SDNAME: \ 747950010eSSimon Moll return VEISD::VVPNAME; 757950010eSSimon Moll #include "VVPNodes.def" 766ac3d8efSSimon Moll // TODO: Map those in VVPNodes.def too 776ac3d8efSSimon Moll case ISD::EXPERIMENTAL_VP_STRIDED_LOAD: 786ac3d8efSSimon Moll return VEISD::VVP_LOAD; 796ac3d8efSSimon Moll case ISD::EXPERIMENTAL_VP_STRIDED_STORE: 806ac3d8efSSimon Moll return VEISD::VVP_STORE; 817950010eSSimon Moll } 8220cde154SKazu Hirata return std::nullopt; 837950010eSSimon Moll } 847950010eSSimon Moll 857d926b71SSimon Moll bool maySafelyIgnoreMask(SDValue Op) { 867d926b71SSimon Moll auto VVPOpc = getVVPOpcode(Op->getOpcode()); 87129b531cSKazu Hirata auto Opc = VVPOpc.value_or(Op->getOpcode()); 887d926b71SSimon Moll 897d926b71SSimon Moll switch (Opc) { 907d926b71SSimon Moll case VEISD::VVP_SDIV: 917d926b71SSimon Moll case VEISD::VVP_UDIV: 927d926b71SSimon Moll case VEISD::VVP_FDIV: 937d926b71SSimon Moll case VEISD::VVP_SELECT: 947d926b71SSimon Moll return false; 957d926b71SSimon Moll 967d926b71SSimon Moll default: 977d926b71SSimon Moll return true; 987d926b71SSimon Moll } 997d926b71SSimon Moll } 1007d926b71SSimon Moll 1014fd77129SSimon Moll bool supportsPackedMode(unsigned Opcode, EVT IdiomVT) { 1024fd77129SSimon Moll bool IsPackedOp = isPackedVectorType(IdiomVT); 1034fd77129SSimon Moll bool IsMaskOp = isMaskType(IdiomVT); 1044fd77129SSimon Moll switch (Opcode) { 1054fd77129SSimon Moll default: 1064fd77129SSimon Moll return false; 1074fd77129SSimon Moll 1084fd77129SSimon Moll case VEISD::VEC_BROADCAST: 1094fd77129SSimon Moll return true; 1104fd77129SSimon Moll #define REGISTER_PACKED(VVP_NAME) case VEISD::VVP_NAME: 1114fd77129SSimon Moll #include "VVPNodes.def" 1124fd77129SSimon Moll return IsPackedOp && !IsMaskOp; 1134fd77129SSimon Moll } 1144fd77129SSimon Moll } 1154fd77129SSimon Moll 1164fd77129SSimon Moll bool isPackingSupportOpcode(unsigned Opc) { 1174fd77129SSimon Moll switch (Opc) { 1184fd77129SSimon Moll case VEISD::VEC_PACK: 1194fd77129SSimon Moll case VEISD::VEC_UNPACK_LO: 1204fd77129SSimon Moll case VEISD::VEC_UNPACK_HI: 1214fd77129SSimon Moll return true; 1224fd77129SSimon Moll } 1234fd77129SSimon Moll return false; 1244fd77129SSimon Moll } 1254fd77129SSimon Moll 1267d926b71SSimon Moll bool isVVPOrVEC(unsigned Opcode) { 1277d926b71SSimon Moll switch (Opcode) { 1287d926b71SSimon Moll case VEISD::VEC_BROADCAST: 1297d926b71SSimon Moll #define ADD_VVP_OP(VVPNAME, ...) case VEISD::VVPNAME: 1307d926b71SSimon Moll #include "VVPNodes.def" 1317d926b71SSimon Moll return true; 1327d926b71SSimon Moll } 1337d926b71SSimon Moll return false; 1347d926b71SSimon Moll } 1357d926b71SSimon Moll 13691fad116SSimon Moll bool isVVPUnaryOp(unsigned VVPOpcode) { 13791fad116SSimon Moll switch (VVPOpcode) { 13891fad116SSimon Moll #define ADD_UNARY_VVP_OP(VVPNAME, ...) \ 13991fad116SSimon Moll case VEISD::VVPNAME: \ 14091fad116SSimon Moll return true; 14191fad116SSimon Moll #include "VVPNodes.def" 14291fad116SSimon Moll } 14391fad116SSimon Moll return false; 14491fad116SSimon Moll } 14591fad116SSimon Moll 1467950010eSSimon Moll bool isVVPBinaryOp(unsigned VVPOpcode) { 1477950010eSSimon Moll switch (VVPOpcode) { 1487950010eSSimon Moll #define ADD_BINARY_VVP_OP(VVPNAME, ...) \ 1497950010eSSimon Moll case VEISD::VVPNAME: \ 1507950010eSSimon Moll return true; 1517950010eSSimon Moll #include "VVPNodes.def" 1527950010eSSimon Moll } 1537950010eSSimon Moll return false; 1547950010eSSimon Moll } 1557950010eSSimon Moll 156f318d1e2SSimon Moll bool isVVPReductionOp(unsigned Opcode) { 157f318d1e2SSimon Moll switch (Opcode) { 158f318d1e2SSimon Moll #define ADD_REDUCE_VVP_OP(VVP_NAME, SDNAME) case VEISD::VVP_NAME: 159f318d1e2SSimon Moll #include "VVPNodes.def" 160f318d1e2SSimon Moll return true; 161f318d1e2SSimon Moll } 162f318d1e2SSimon Moll return false; 163f318d1e2SSimon Moll } 164f318d1e2SSimon Moll 1657d926b71SSimon Moll // Return the AVL operand position for this VVP or VEC Op. 166b0df7040SFangrui Song std::optional<int> getAVLPos(unsigned Opc) { 1677d926b71SSimon Moll // This is only available for VP SDNodes 1687d926b71SSimon Moll auto PosOpt = ISD::getVPExplicitVectorLengthIdx(Opc); 1697d926b71SSimon Moll if (PosOpt) 1707d926b71SSimon Moll return *PosOpt; 1717d926b71SSimon Moll 1727d926b71SSimon Moll // VVP Opcodes. 1737d926b71SSimon Moll if (isVVPBinaryOp(Opc)) 1747d926b71SSimon Moll return 3; 1757d926b71SSimon Moll 1767d926b71SSimon Moll // VM Opcodes. 1777d926b71SSimon Moll switch (Opc) { 1787d926b71SSimon Moll case VEISD::VEC_BROADCAST: 1797d926b71SSimon Moll return 1; 1807d926b71SSimon Moll case VEISD::VVP_SELECT: 1817d926b71SSimon Moll return 3; 182c574c54eSSimon Moll case VEISD::VVP_LOAD: 183c574c54eSSimon Moll return 4; 184c574c54eSSimon Moll case VEISD::VVP_STORE: 185c574c54eSSimon Moll return 5; 1867d926b71SSimon Moll } 1877d926b71SSimon Moll 18820cde154SKazu Hirata return std::nullopt; 1897d926b71SSimon Moll } 1907d926b71SSimon Moll 191b0df7040SFangrui Song std::optional<int> getMaskPos(unsigned Opc) { 1924fd77129SSimon Moll // This is only available for VP SDNodes 1934fd77129SSimon Moll auto PosOpt = ISD::getVPMaskIdx(Opc); 1944fd77129SSimon Moll if (PosOpt) 1954fd77129SSimon Moll return *PosOpt; 1964fd77129SSimon Moll 1974fd77129SSimon Moll // VVP Opcodes. 1984fd77129SSimon Moll if (isVVPBinaryOp(Opc)) 1994fd77129SSimon Moll return 2; 2004fd77129SSimon Moll 2019ebaec46SSimon Moll // Other opcodes. 2024fd77129SSimon Moll switch (Opc) { 2039ebaec46SSimon Moll case ISD::MSTORE: 2049ebaec46SSimon Moll return 4; 2059ebaec46SSimon Moll case ISD::MLOAD: 2069ebaec46SSimon Moll return 3; 2074fd77129SSimon Moll case VEISD::VVP_SELECT: 2084fd77129SSimon Moll return 2; 2094fd77129SSimon Moll } 2104fd77129SSimon Moll 21120cde154SKazu Hirata return std::nullopt; 2124fd77129SSimon Moll } 2134fd77129SSimon Moll 2147d926b71SSimon Moll bool isLegalAVL(SDValue AVL) { return AVL->getOpcode() == VEISD::LEGALAVL; } 2157d926b71SSimon Moll 2169ebaec46SSimon Moll /// Node Properties { 2179ebaec46SSimon Moll 2189ebaec46SSimon Moll SDValue getNodeChain(SDValue Op) { 2199ebaec46SSimon Moll if (MemSDNode *MemN = dyn_cast<MemSDNode>(Op.getNode())) 2209ebaec46SSimon Moll return MemN->getChain(); 2219ebaec46SSimon Moll 2229ebaec46SSimon Moll switch (Op->getOpcode()) { 2239ebaec46SSimon Moll case VEISD::VVP_LOAD: 2249ebaec46SSimon Moll case VEISD::VVP_STORE: 2259ebaec46SSimon Moll return Op->getOperand(0); 2269ebaec46SSimon Moll } 2279ebaec46SSimon Moll return SDValue(); 2289ebaec46SSimon Moll } 2299ebaec46SSimon Moll 2309ebaec46SSimon Moll SDValue getMemoryPtr(SDValue Op) { 2319ebaec46SSimon Moll if (auto *MemN = dyn_cast<MemSDNode>(Op.getNode())) 2329ebaec46SSimon Moll return MemN->getBasePtr(); 2339ebaec46SSimon Moll 2349ebaec46SSimon Moll switch (Op->getOpcode()) { 2359ebaec46SSimon Moll case VEISD::VVP_LOAD: 2369ebaec46SSimon Moll return Op->getOperand(1); 2379ebaec46SSimon Moll case VEISD::VVP_STORE: 2389ebaec46SSimon Moll return Op->getOperand(2); 2399ebaec46SSimon Moll } 2409ebaec46SSimon Moll return SDValue(); 2419ebaec46SSimon Moll } 2429ebaec46SSimon Moll 243b0df7040SFangrui Song std::optional<EVT> getIdiomaticVectorType(SDNode *Op) { 2449ebaec46SSimon Moll unsigned OC = Op->getOpcode(); 2459ebaec46SSimon Moll 2469ebaec46SSimon Moll // For memory ops -> the transfered data type 2479ebaec46SSimon Moll if (auto MemN = dyn_cast<MemSDNode>(Op)) 2489ebaec46SSimon Moll return MemN->getMemoryVT(); 2499ebaec46SSimon Moll 2509ebaec46SSimon Moll switch (OC) { 2519ebaec46SSimon Moll // Standard ISD. 2529ebaec46SSimon Moll case ISD::SELECT: // not aliased with VVP_SELECT 2539ebaec46SSimon Moll case ISD::CONCAT_VECTORS: 2549ebaec46SSimon Moll case ISD::EXTRACT_SUBVECTOR: 2559ebaec46SSimon Moll case ISD::VECTOR_SHUFFLE: 2569ebaec46SSimon Moll case ISD::BUILD_VECTOR: 2579ebaec46SSimon Moll case ISD::SCALAR_TO_VECTOR: 2589ebaec46SSimon Moll return Op->getValueType(0); 2599ebaec46SSimon Moll } 2609ebaec46SSimon Moll 2619ebaec46SSimon Moll // Translate to VVP where possible. 262f318d1e2SSimon Moll unsigned OriginalOC = OC; 2639ebaec46SSimon Moll if (auto VVPOpc = getVVPOpcode(OC)) 2649ebaec46SSimon Moll OC = *VVPOpc; 2659ebaec46SSimon Moll 266f318d1e2SSimon Moll if (isVVPReductionOp(OC)) 267f318d1e2SSimon Moll return Op->getOperand(hasReductionStartParam(OriginalOC) ? 1 : 0) 268f318d1e2SSimon Moll .getValueType(); 269f318d1e2SSimon Moll 2709ebaec46SSimon Moll switch (OC) { 2719ebaec46SSimon Moll default: 2729ebaec46SSimon Moll case VEISD::VVP_SETCC: 2739ebaec46SSimon Moll return Op->getOperand(0).getValueType(); 2749ebaec46SSimon Moll 2759ebaec46SSimon Moll case VEISD::VVP_SELECT: 2769ebaec46SSimon Moll #define ADD_BINARY_VVP_OP(VVP_NAME, ...) case VEISD::VVP_NAME: 2779ebaec46SSimon Moll #include "VVPNodes.def" 2789ebaec46SSimon Moll return Op->getValueType(0); 2799ebaec46SSimon Moll 2809ebaec46SSimon Moll case VEISD::VVP_LOAD: 2819ebaec46SSimon Moll return Op->getValueType(0); 2829ebaec46SSimon Moll 2839ebaec46SSimon Moll case VEISD::VVP_STORE: 2849ebaec46SSimon Moll return Op->getOperand(1)->getValueType(0); 2859ebaec46SSimon Moll 2869ebaec46SSimon Moll // VEC 2879ebaec46SSimon Moll case VEISD::VEC_BROADCAST: 2889ebaec46SSimon Moll return Op->getValueType(0); 2899ebaec46SSimon Moll } 2909ebaec46SSimon Moll } 2919ebaec46SSimon Moll 2929ebaec46SSimon Moll SDValue getLoadStoreStride(SDValue Op, VECustomDAG &CDAG) { 2936ac3d8efSSimon Moll switch (Op->getOpcode()) { 2946ac3d8efSSimon Moll case VEISD::VVP_STORE: 2959ebaec46SSimon Moll return Op->getOperand(3); 2966ac3d8efSSimon Moll case VEISD::VVP_LOAD: 2979ebaec46SSimon Moll return Op->getOperand(2); 2986ac3d8efSSimon Moll } 2996ac3d8efSSimon Moll 3006ac3d8efSSimon Moll if (auto *StoreN = dyn_cast<VPStridedStoreSDNode>(Op.getNode())) 3016ac3d8efSSimon Moll return StoreN->getStride(); 3026ac3d8efSSimon Moll if (auto *StoreN = dyn_cast<VPStridedLoadSDNode>(Op.getNode())) 3036ac3d8efSSimon Moll return StoreN->getStride(); 3049ebaec46SSimon Moll 3059ebaec46SSimon Moll if (isa<MemSDNode>(Op.getNode())) { 3069ebaec46SSimon Moll // Regular MLOAD/MSTORE/LOAD/STORE 3079ebaec46SSimon Moll // No stride argument -> use the contiguous element size as stride. 3089ebaec46SSimon Moll uint64_t ElemStride = getIdiomaticVectorType(Op.getNode()) 3099ebaec46SSimon Moll ->getVectorElementType() 3109ebaec46SSimon Moll .getStoreSize(); 3119ebaec46SSimon Moll return CDAG.getConstant(ElemStride, MVT::i64); 3129ebaec46SSimon Moll } 3139ebaec46SSimon Moll return SDValue(); 3149ebaec46SSimon Moll } 3159ebaec46SSimon Moll 316a5f12623SSimon Moll SDValue getGatherScatterIndex(SDValue Op) { 317a5f12623SSimon Moll if (auto *N = dyn_cast<MaskedGatherScatterSDNode>(Op.getNode())) 318a5f12623SSimon Moll return N->getIndex(); 319a5f12623SSimon Moll if (auto *N = dyn_cast<VPGatherScatterSDNode>(Op.getNode())) 320a5f12623SSimon Moll return N->getIndex(); 321a5f12623SSimon Moll return SDValue(); 322a5f12623SSimon Moll } 323a5f12623SSimon Moll 324a5f12623SSimon Moll SDValue getGatherScatterScale(SDValue Op) { 325a5f12623SSimon Moll if (auto *N = dyn_cast<MaskedGatherScatterSDNode>(Op.getNode())) 326a5f12623SSimon Moll return N->getScale(); 327a5f12623SSimon Moll if (auto *N = dyn_cast<VPGatherScatterSDNode>(Op.getNode())) 328a5f12623SSimon Moll return N->getScale(); 329a5f12623SSimon Moll return SDValue(); 330a5f12623SSimon Moll } 331a5f12623SSimon Moll 3329ebaec46SSimon Moll SDValue getStoredValue(SDValue Op) { 3339ebaec46SSimon Moll switch (Op->getOpcode()) { 3346ac3d8efSSimon Moll case ISD::EXPERIMENTAL_VP_STRIDED_STORE: 3359ebaec46SSimon Moll case VEISD::VVP_STORE: 3369ebaec46SSimon Moll return Op->getOperand(1); 3379ebaec46SSimon Moll } 3389ebaec46SSimon Moll if (auto *StoreN = dyn_cast<StoreSDNode>(Op.getNode())) 3399ebaec46SSimon Moll return StoreN->getValue(); 3409ebaec46SSimon Moll if (auto *StoreN = dyn_cast<MaskedStoreSDNode>(Op.getNode())) 3419ebaec46SSimon Moll return StoreN->getValue(); 3426ac3d8efSSimon Moll if (auto *StoreN = dyn_cast<VPStridedStoreSDNode>(Op.getNode())) 3436ac3d8efSSimon Moll return StoreN->getValue(); 3449ebaec46SSimon Moll if (auto *StoreN = dyn_cast<VPStoreSDNode>(Op.getNode())) 3459ebaec46SSimon Moll return StoreN->getValue(); 346a5f12623SSimon Moll if (auto *StoreN = dyn_cast<MaskedScatterSDNode>(Op.getNode())) 347a5f12623SSimon Moll return StoreN->getValue(); 348a5f12623SSimon Moll if (auto *StoreN = dyn_cast<VPScatterSDNode>(Op.getNode())) 349a5f12623SSimon Moll return StoreN->getValue(); 3509ebaec46SSimon Moll return SDValue(); 3519ebaec46SSimon Moll } 3529ebaec46SSimon Moll 3539ebaec46SSimon Moll SDValue getNodePassthru(SDValue Op) { 3549ebaec46SSimon Moll if (auto *N = dyn_cast<MaskedLoadSDNode>(Op.getNode())) 3559ebaec46SSimon Moll return N->getPassThru(); 356a5f12623SSimon Moll if (auto *N = dyn_cast<MaskedGatherSDNode>(Op.getNode())) 357a5f12623SSimon Moll return N->getPassThru(); 358a5f12623SSimon Moll 3599ebaec46SSimon Moll return SDValue(); 3609ebaec46SSimon Moll } 3619ebaec46SSimon Moll 362f318d1e2SSimon Moll bool hasReductionStartParam(unsigned OPC) { 363f318d1e2SSimon Moll // TODO: Ordered reduction opcodes. 364f318d1e2SSimon Moll if (ISD::isVPReduction(OPC)) 365f318d1e2SSimon Moll return true; 366f318d1e2SSimon Moll return false; 367f318d1e2SSimon Moll } 368f318d1e2SSimon Moll 369f318d1e2SSimon Moll unsigned getScalarReductionOpcode(unsigned VVPOC, bool IsMask) { 370f318d1e2SSimon Moll assert(!IsMask && "Mask reduction isel"); 371f318d1e2SSimon Moll 372f318d1e2SSimon Moll switch (VVPOC) { 373f318d1e2SSimon Moll #define HANDLE_VVP_REDUCE_TO_SCALAR(VVP_RED_ISD, REDUCE_ISD) \ 374f318d1e2SSimon Moll case VEISD::VVP_RED_ISD: \ 375f318d1e2SSimon Moll return ISD::REDUCE_ISD; 376f318d1e2SSimon Moll #include "VVPNodes.def" 377f318d1e2SSimon Moll default: 378f318d1e2SSimon Moll break; 379f318d1e2SSimon Moll } 380f318d1e2SSimon Moll llvm_unreachable("Cannot not scalarize this reduction Opcode!"); 381f318d1e2SSimon Moll } 382f318d1e2SSimon Moll 3839ebaec46SSimon Moll /// } Node Properties 3849ebaec46SSimon Moll 3857d926b71SSimon Moll SDValue getNodeAVL(SDValue Op) { 3867d926b71SSimon Moll auto PosOpt = getAVLPos(Op->getOpcode()); 3877d926b71SSimon Moll return PosOpt ? Op->getOperand(*PosOpt) : SDValue(); 3887d926b71SSimon Moll } 3897d926b71SSimon Moll 3904fd77129SSimon Moll SDValue getNodeMask(SDValue Op) { 3914fd77129SSimon Moll auto PosOpt = getMaskPos(Op->getOpcode()); 3924fd77129SSimon Moll return PosOpt ? Op->getOperand(*PosOpt) : SDValue(); 3934fd77129SSimon Moll } 3944fd77129SSimon Moll 3957d926b71SSimon Moll std::pair<SDValue, bool> getAnnotatedNodeAVL(SDValue Op) { 3967d926b71SSimon Moll SDValue AVL = getNodeAVL(Op); 3977d926b71SSimon Moll if (!AVL) 3987d926b71SSimon Moll return {SDValue(), true}; 3997d926b71SSimon Moll if (isLegalAVL(AVL)) 4007d926b71SSimon Moll return {AVL->getOperand(0), true}; 4017d926b71SSimon Moll return {AVL, false}; 4027d926b71SSimon Moll } 4037d926b71SSimon Moll 4041b09d0c4SSimon Moll SDValue VECustomDAG::getConstant(uint64_t Val, EVT VT, bool IsTarget, 4051b09d0c4SSimon Moll bool IsOpaque) const { 4061b09d0c4SSimon Moll return DAG.getConstant(Val, DL, VT, IsTarget, IsOpaque); 4071b09d0c4SSimon Moll } 4081b09d0c4SSimon Moll 40953efbc15SSimon Moll SDValue VECustomDAG::getConstantMask(Packing Packing, bool AllTrue) const { 41053efbc15SSimon Moll auto MaskVT = getLegalVectorType(Packing, MVT::i1); 41153efbc15SSimon Moll 41253efbc15SSimon Moll // VEISelDAGtoDAG will replace this pattern with the constant-true VM. 413*f499a3feSCraig Topper auto TrueVal = DAG.getAllOnesConstant(DL, MVT::i32); 41453efbc15SSimon Moll auto AVL = getConstant(MaskVT.getVectorNumElements(), MVT::i32); 41553efbc15SSimon Moll auto Res = getNode(VEISD::VEC_BROADCAST, MaskVT, {TrueVal, AVL}); 41653efbc15SSimon Moll if (AllTrue) 41753efbc15SSimon Moll return Res; 41853efbc15SSimon Moll 41953efbc15SSimon Moll return DAG.getNOT(DL, Res, Res.getValueType()); 42053efbc15SSimon Moll } 42153efbc15SSimon Moll 42253efbc15SSimon Moll SDValue VECustomDAG::getMaskBroadcast(EVT ResultVT, SDValue Scalar, 42353efbc15SSimon Moll SDValue AVL) const { 42453efbc15SSimon Moll // Constant mask splat. 42553efbc15SSimon Moll if (auto BcConst = dyn_cast<ConstantSDNode>(Scalar)) 42653efbc15SSimon Moll return getConstantMask(getTypePacking(ResultVT), 42753efbc15SSimon Moll BcConst->getSExtValue() != 0); 42853efbc15SSimon Moll 42953efbc15SSimon Moll // Expand the broadcast to a vector comparison. 43053efbc15SSimon Moll auto ScalarBoolVT = Scalar.getSimpleValueType(); 43153efbc15SSimon Moll assert(ScalarBoolVT == MVT::i32); 43253efbc15SSimon Moll 43353efbc15SSimon Moll // Cast to i32 ty. 43453efbc15SSimon Moll SDValue CmpElem = DAG.getSExtOrTrunc(Scalar, DL, MVT::i32); 43553efbc15SSimon Moll unsigned ElemCount = ResultVT.getVectorNumElements(); 43653efbc15SSimon Moll MVT CmpVecTy = MVT::getVectorVT(ScalarBoolVT, ElemCount); 43753efbc15SSimon Moll 43853efbc15SSimon Moll // Broadcast to vector. 43953efbc15SSimon Moll SDValue BCVec = 44053efbc15SSimon Moll DAG.getNode(VEISD::VEC_BROADCAST, DL, CmpVecTy, {CmpElem, AVL}); 44153efbc15SSimon Moll SDValue ZeroVec = 44253efbc15SSimon Moll getBroadcast(CmpVecTy, {DAG.getConstant(0, DL, ScalarBoolVT)}, AVL); 44353efbc15SSimon Moll 44453efbc15SSimon Moll MVT BoolVecTy = MVT::getVectorVT(MVT::i1, ElemCount); 44553efbc15SSimon Moll 44653efbc15SSimon Moll // Broadcast(Data) != Broadcast(0) 44753efbc15SSimon Moll // TODO: Use a VVP operation for this. 44853efbc15SSimon Moll return DAG.getSetCC(DL, BoolVecTy, BCVec, ZeroVec, ISD::CondCode::SETNE); 44953efbc15SSimon Moll } 45053efbc15SSimon Moll 4517950010eSSimon Moll SDValue VECustomDAG::getBroadcast(EVT ResultVT, SDValue Scalar, 4527950010eSSimon Moll SDValue AVL) const { 4535ceb0bc7SSimon Moll assert(ResultVT.isVector()); 4545ceb0bc7SSimon Moll auto ScaVT = Scalar.getValueType(); 45553efbc15SSimon Moll 45653efbc15SSimon Moll if (isMaskType(ResultVT)) 45753efbc15SSimon Moll return getMaskBroadcast(ResultVT, Scalar, AVL); 4585ceb0bc7SSimon Moll 4595ceb0bc7SSimon Moll if (isPackedVectorType(ResultVT)) { 4605ceb0bc7SSimon Moll // v512x packed mode broadcast 4615ceb0bc7SSimon Moll // Replicate the scalar reg (f32 or i32) onto the opposing half of the full 4625ceb0bc7SSimon Moll // scalar register. If it's an I64 type, assume that this has already 4635ceb0bc7SSimon Moll // happened. 4645ceb0bc7SSimon Moll if (ScaVT == MVT::f32) { 4655ceb0bc7SSimon Moll Scalar = getNode(VEISD::REPL_F32, MVT::i64, Scalar); 4665ceb0bc7SSimon Moll } else if (ScaVT == MVT::i32) { 4675ceb0bc7SSimon Moll Scalar = getNode(VEISD::REPL_I32, MVT::i64, Scalar); 4685ceb0bc7SSimon Moll } 4695ceb0bc7SSimon Moll } 4705ceb0bc7SSimon Moll 4717950010eSSimon Moll return getNode(VEISD::VEC_BROADCAST, ResultVT, {Scalar, AVL}); 4727950010eSSimon Moll } 4737950010eSSimon Moll 4747d926b71SSimon Moll SDValue VECustomDAG::annotateLegalAVL(SDValue AVL) const { 4757d926b71SSimon Moll if (isLegalAVL(AVL)) 4767d926b71SSimon Moll return AVL; 4777d926b71SSimon Moll return getNode(VEISD::LEGALAVL, AVL.getValueType(), AVL); 4787d926b71SSimon Moll } 4797d926b71SSimon Moll 480cf964eb5SSimon Moll SDValue VECustomDAG::getUnpack(EVT DestVT, SDValue Vec, PackElem Part, 4814fd77129SSimon Moll SDValue AVL) const { 4824fd77129SSimon Moll assert(getAnnotatedNodeAVL(AVL).second && "Expected a pack-legalized AVL"); 4834fd77129SSimon Moll 484cf964eb5SSimon Moll // TODO: Peek through VEC_PACK and VEC_BROADCAST(REPL_<sth> ..) operands. 485cf964eb5SSimon Moll unsigned OC = 486cf964eb5SSimon Moll (Part == PackElem::Lo) ? VEISD::VEC_UNPACK_LO : VEISD::VEC_UNPACK_HI; 487cf964eb5SSimon Moll return DAG.getNode(OC, DL, DestVT, Vec, AVL); 488cf964eb5SSimon Moll } 489cf964eb5SSimon Moll 490cf964eb5SSimon Moll SDValue VECustomDAG::getPack(EVT DestVT, SDValue LoVec, SDValue HiVec, 4914fd77129SSimon Moll SDValue AVL) const { 4924fd77129SSimon Moll assert(getAnnotatedNodeAVL(AVL).second && "Expected a pack-legalized AVL"); 4934fd77129SSimon Moll 494cf964eb5SSimon Moll // TODO: Peek through VEC_UNPACK_LO|HI operands. 495cf964eb5SSimon Moll return DAG.getNode(VEISD::VEC_PACK, DL, DestVT, LoVec, HiVec, AVL); 496cf964eb5SSimon Moll } 497cf964eb5SSimon Moll 4984fd77129SSimon Moll VETargetMasks VECustomDAG::getTargetSplitMask(SDValue RawMask, SDValue RawAVL, 4994fd77129SSimon Moll PackElem Part) const { 5004fd77129SSimon Moll // Adjust AVL for this part 5014fd77129SSimon Moll SDValue NewAVL; 5024fd77129SSimon Moll SDValue OneV = getConstant(1, MVT::i32); 5034fd77129SSimon Moll if (Part == PackElem::Hi) 5044fd77129SSimon Moll NewAVL = getNode(ISD::ADD, MVT::i32, {RawAVL, OneV}); 5054fd77129SSimon Moll else 5064fd77129SSimon Moll NewAVL = RawAVL; 5074fd77129SSimon Moll NewAVL = getNode(ISD::SRL, MVT::i32, {NewAVL, OneV}); 5084fd77129SSimon Moll 5094fd77129SSimon Moll NewAVL = annotateLegalAVL(NewAVL); 5104fd77129SSimon Moll 5114fd77129SSimon Moll // Legalize Mask (unpack or all-true) 5124fd77129SSimon Moll SDValue NewMask; 5134fd77129SSimon Moll if (!RawMask) 5144fd77129SSimon Moll NewMask = getConstantMask(Packing::Normal, true); 5154fd77129SSimon Moll else 5164fd77129SSimon Moll NewMask = getUnpack(MVT::v256i1, RawMask, Part, NewAVL); 5174fd77129SSimon Moll 5184fd77129SSimon Moll return VETargetMasks(NewMask, NewAVL); 5194fd77129SSimon Moll } 5204fd77129SSimon Moll 521c574c54eSSimon Moll SDValue VECustomDAG::getSplitPtrOffset(SDValue Ptr, SDValue ByteStride, 522c574c54eSSimon Moll PackElem Part) const { 523c574c54eSSimon Moll // High starts at base ptr but has more significant bits in the 64bit vector 524c574c54eSSimon Moll // element. 525c574c54eSSimon Moll if (Part == PackElem::Hi) 526c574c54eSSimon Moll return Ptr; 527c574c54eSSimon Moll return getNode(ISD::ADD, MVT::i64, {Ptr, ByteStride}); 528c574c54eSSimon Moll } 529c574c54eSSimon Moll 530c574c54eSSimon Moll SDValue VECustomDAG::getSplitPtrStride(SDValue PackStride) const { 531c574c54eSSimon Moll if (auto ConstBytes = dyn_cast<ConstantSDNode>(PackStride)) 532c574c54eSSimon Moll return getConstant(2 * ConstBytes->getSExtValue(), MVT::i64); 533c574c54eSSimon Moll return getNode(ISD::SHL, MVT::i64, {PackStride, getConstant(1, MVT::i32)}); 534c574c54eSSimon Moll } 535c574c54eSSimon Moll 536a5f12623SSimon Moll SDValue VECustomDAG::getGatherScatterAddress(SDValue BasePtr, SDValue Scale, 537a5f12623SSimon Moll SDValue Index, SDValue Mask, 538a5f12623SSimon Moll SDValue AVL) const { 539a5f12623SSimon Moll EVT IndexVT = Index.getValueType(); 540a5f12623SSimon Moll 541a5f12623SSimon Moll // Apply scale. 542a5f12623SSimon Moll SDValue ScaledIndex; 543a5f12623SSimon Moll if (!Scale || isOneConstant(Scale)) 544a5f12623SSimon Moll ScaledIndex = Index; 545a5f12623SSimon Moll else { 546a5f12623SSimon Moll SDValue ScaleBroadcast = getBroadcast(IndexVT, Scale, AVL); 547a5f12623SSimon Moll ScaledIndex = 548a5f12623SSimon Moll getNode(VEISD::VVP_MUL, IndexVT, {Index, ScaleBroadcast, Mask, AVL}); 549a5f12623SSimon Moll } 550a5f12623SSimon Moll 551a5f12623SSimon Moll // Add basePtr. 552a5f12623SSimon Moll if (isNullConstant(BasePtr)) 553a5f12623SSimon Moll return ScaledIndex; 554a5f12623SSimon Moll 555a5f12623SSimon Moll // re-constitute pointer vector (basePtr + index * scale) 556a5f12623SSimon Moll SDValue BaseBroadcast = getBroadcast(IndexVT, BasePtr, AVL); 557a5f12623SSimon Moll auto ResPtr = 558a5f12623SSimon Moll getNode(VEISD::VVP_ADD, IndexVT, {BaseBroadcast, ScaledIndex, Mask, AVL}); 559a5f12623SSimon Moll return ResPtr; 560a5f12623SSimon Moll } 561a5f12623SSimon Moll 562f318d1e2SSimon Moll SDValue VECustomDAG::getLegalReductionOpVVP(unsigned VVPOpcode, EVT ResVT, 563f318d1e2SSimon Moll SDValue StartV, SDValue VectorV, 564f318d1e2SSimon Moll SDValue Mask, SDValue AVL, 565f318d1e2SSimon Moll SDNodeFlags Flags) const { 566f318d1e2SSimon Moll 567f318d1e2SSimon Moll // Optionally attach the start param with a scalar op (where it is 568f318d1e2SSimon Moll // unsupported). 569f318d1e2SSimon Moll bool scalarizeStartParam = StartV && !hasReductionStartParam(VVPOpcode); 570f318d1e2SSimon Moll bool IsMaskReduction = isMaskType(VectorV.getValueType()); 571f318d1e2SSimon Moll assert(!IsMaskReduction && "TODO Implement"); 572f318d1e2SSimon Moll auto AttachStartValue = [&](SDValue ReductionResV) { 573f318d1e2SSimon Moll if (!scalarizeStartParam) 574f318d1e2SSimon Moll return ReductionResV; 575f318d1e2SSimon Moll auto ScalarOC = getScalarReductionOpcode(VVPOpcode, IsMaskReduction); 576f318d1e2SSimon Moll return getNode(ScalarOC, ResVT, {StartV, ReductionResV}); 577f318d1e2SSimon Moll }; 578f318d1e2SSimon Moll 579f318d1e2SSimon Moll // Fixup: Always Use sequential 'fmul' reduction. 580f318d1e2SSimon Moll if (!scalarizeStartParam && StartV) { 581f318d1e2SSimon Moll assert(hasReductionStartParam(VVPOpcode)); 582f318d1e2SSimon Moll return AttachStartValue( 583f318d1e2SSimon Moll getNode(VVPOpcode, ResVT, {StartV, VectorV, Mask, AVL}, Flags)); 584f318d1e2SSimon Moll } else 585f318d1e2SSimon Moll return AttachStartValue( 586f318d1e2SSimon Moll getNode(VVPOpcode, ResVT, {VectorV, Mask, AVL}, Flags)); 587f318d1e2SSimon Moll } 588f318d1e2SSimon Moll 5891b09d0c4SSimon Moll } // namespace llvm 590