xref: /llvm-project/llvm/lib/Target/VE/VECustomDAG.cpp (revision f499a3fe5fb6fd816d35b541e67a3761093cfded)
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