1 //===-- VECustomDAG.h - VE Custom DAG Nodes ------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines the interfaces that VE uses to lower LLVM code into a 10 // selection DAG. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "VECustomDAG.h" 15 16 #ifndef DEBUG_TYPE 17 #define DEBUG_TYPE "vecustomdag" 18 #endif 19 20 namespace llvm { 21 22 bool isPackedVectorType(EVT SomeVT) { 23 if (!SomeVT.isVector()) 24 return false; 25 return SomeVT.getVectorNumElements() > StandardVectorWidth; 26 } 27 28 MVT getLegalVectorType(Packing P, MVT ElemVT) { 29 return MVT::getVectorVT(ElemVT, P == Packing::Normal ? StandardVectorWidth 30 : PackedVectorWidth); 31 } 32 33 Packing getTypePacking(EVT VT) { 34 assert(VT.isVector()); 35 return isPackedVectorType(VT) ? Packing::Dense : Packing::Normal; 36 } 37 38 bool isMaskType(EVT SomeVT) { 39 if (!SomeVT.isVector()) 40 return false; 41 return SomeVT.getVectorElementType() == MVT::i1; 42 } 43 44 /// \returns the VVP_* SDNode opcode corresponsing to \p OC. 45 Optional<unsigned> getVVPOpcode(unsigned Opcode) { 46 switch (Opcode) { 47 #define HANDLE_VP_TO_VVP(VPOPC, VVPNAME) \ 48 case ISD::VPOPC: \ 49 return VEISD::VVPNAME; 50 #define ADD_VVP_OP(VVPNAME, SDNAME) \ 51 case VEISD::VVPNAME: \ 52 case ISD::SDNAME: \ 53 return VEISD::VVPNAME; 54 #include "VVPNodes.def" 55 } 56 return None; 57 } 58 59 bool maySafelyIgnoreMask(SDValue Op) { 60 auto VVPOpc = getVVPOpcode(Op->getOpcode()); 61 auto Opc = VVPOpc.getValueOr(Op->getOpcode()); 62 63 switch (Opc) { 64 case VEISD::VVP_SDIV: 65 case VEISD::VVP_UDIV: 66 case VEISD::VVP_FDIV: 67 case VEISD::VVP_SELECT: 68 return false; 69 70 default: 71 return true; 72 } 73 } 74 75 bool isVVPOrVEC(unsigned Opcode) { 76 switch (Opcode) { 77 case VEISD::VEC_BROADCAST: 78 #define ADD_VVP_OP(VVPNAME, ...) case VEISD::VVPNAME: 79 #include "VVPNodes.def" 80 return true; 81 } 82 return false; 83 } 84 85 bool isVVPBinaryOp(unsigned VVPOpcode) { 86 switch (VVPOpcode) { 87 #define ADD_BINARY_VVP_OP(VVPNAME, ...) \ 88 case VEISD::VVPNAME: \ 89 return true; 90 #include "VVPNodes.def" 91 } 92 return false; 93 } 94 95 // Return the AVL operand position for this VVP or VEC Op. 96 Optional<int> getAVLPos(unsigned Opc) { 97 // This is only available for VP SDNodes 98 auto PosOpt = ISD::getVPExplicitVectorLengthIdx(Opc); 99 if (PosOpt) 100 return *PosOpt; 101 102 // VVP Opcodes. 103 if (isVVPBinaryOp(Opc)) 104 return 3; 105 106 // VM Opcodes. 107 switch (Opc) { 108 case VEISD::VEC_BROADCAST: 109 return 1; 110 case VEISD::VVP_SELECT: 111 return 3; 112 } 113 114 return None; 115 } 116 117 bool isLegalAVL(SDValue AVL) { return AVL->getOpcode() == VEISD::LEGALAVL; } 118 119 SDValue getNodeAVL(SDValue Op) { 120 auto PosOpt = getAVLPos(Op->getOpcode()); 121 return PosOpt ? Op->getOperand(*PosOpt) : SDValue(); 122 } 123 124 std::pair<SDValue, bool> getAnnotatedNodeAVL(SDValue Op) { 125 SDValue AVL = getNodeAVL(Op); 126 if (!AVL) 127 return {SDValue(), true}; 128 if (isLegalAVL(AVL)) 129 return {AVL->getOperand(0), true}; 130 return {AVL, false}; 131 } 132 133 SDValue VECustomDAG::getConstant(uint64_t Val, EVT VT, bool IsTarget, 134 bool IsOpaque) const { 135 return DAG.getConstant(Val, DL, VT, IsTarget, IsOpaque); 136 } 137 138 SDValue VECustomDAG::getConstantMask(Packing Packing, bool AllTrue) const { 139 auto MaskVT = getLegalVectorType(Packing, MVT::i1); 140 141 // VEISelDAGtoDAG will replace this pattern with the constant-true VM. 142 auto TrueVal = DAG.getConstant(-1, DL, MVT::i32); 143 auto AVL = getConstant(MaskVT.getVectorNumElements(), MVT::i32); 144 auto Res = getNode(VEISD::VEC_BROADCAST, MaskVT, {TrueVal, AVL}); 145 if (AllTrue) 146 return Res; 147 148 return DAG.getNOT(DL, Res, Res.getValueType()); 149 } 150 151 SDValue VECustomDAG::getMaskBroadcast(EVT ResultVT, SDValue Scalar, 152 SDValue AVL) const { 153 // Constant mask splat. 154 if (auto BcConst = dyn_cast<ConstantSDNode>(Scalar)) 155 return getConstantMask(getTypePacking(ResultVT), 156 BcConst->getSExtValue() != 0); 157 158 // Expand the broadcast to a vector comparison. 159 auto ScalarBoolVT = Scalar.getSimpleValueType(); 160 assert(ScalarBoolVT == MVT::i32); 161 162 // Cast to i32 ty. 163 SDValue CmpElem = DAG.getSExtOrTrunc(Scalar, DL, MVT::i32); 164 unsigned ElemCount = ResultVT.getVectorNumElements(); 165 MVT CmpVecTy = MVT::getVectorVT(ScalarBoolVT, ElemCount); 166 167 // Broadcast to vector. 168 SDValue BCVec = 169 DAG.getNode(VEISD::VEC_BROADCAST, DL, CmpVecTy, {CmpElem, AVL}); 170 SDValue ZeroVec = 171 getBroadcast(CmpVecTy, {DAG.getConstant(0, DL, ScalarBoolVT)}, AVL); 172 173 MVT BoolVecTy = MVT::getVectorVT(MVT::i1, ElemCount); 174 175 // Broadcast(Data) != Broadcast(0) 176 // TODO: Use a VVP operation for this. 177 return DAG.getSetCC(DL, BoolVecTy, BCVec, ZeroVec, ISD::CondCode::SETNE); 178 } 179 180 SDValue VECustomDAG::getBroadcast(EVT ResultVT, SDValue Scalar, 181 SDValue AVL) const { 182 assert(ResultVT.isVector()); 183 auto ScaVT = Scalar.getValueType(); 184 185 if (isMaskType(ResultVT)) 186 return getMaskBroadcast(ResultVT, Scalar, AVL); 187 188 if (isPackedVectorType(ResultVT)) { 189 // v512x packed mode broadcast 190 // Replicate the scalar reg (f32 or i32) onto the opposing half of the full 191 // scalar register. If it's an I64 type, assume that this has already 192 // happened. 193 if (ScaVT == MVT::f32) { 194 Scalar = getNode(VEISD::REPL_F32, MVT::i64, Scalar); 195 } else if (ScaVT == MVT::i32) { 196 Scalar = getNode(VEISD::REPL_I32, MVT::i64, Scalar); 197 } 198 } 199 200 return getNode(VEISD::VEC_BROADCAST, ResultVT, {Scalar, AVL}); 201 } 202 203 SDValue VECustomDAG::annotateLegalAVL(SDValue AVL) const { 204 if (isLegalAVL(AVL)) 205 return AVL; 206 return getNode(VEISD::LEGALAVL, AVL.getValueType(), AVL); 207 } 208 209 } // namespace llvm 210