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