xref: /llvm-project/clang/lib/Support/RISCVVIntrinsicUtils.cpp (revision 239127d731e633f89b912b0775b638c0e8b4a9eb)
1f26c41e8SKito Cheng //===- RISCVVIntrinsicUtils.cpp - RISC-V Vector Intrinsic Utils -*- C++ -*-===//
2f26c41e8SKito Cheng //
3f26c41e8SKito Cheng // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4f26c41e8SKito Cheng // See https://llvm.org/LICENSE.txt for license information.
5f26c41e8SKito Cheng // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f26c41e8SKito Cheng //
7f26c41e8SKito Cheng //===----------------------------------------------------------------------===//
8f26c41e8SKito Cheng 
9f26c41e8SKito Cheng #include "clang/Support/RISCVVIntrinsicUtils.h"
10f26c41e8SKito Cheng #include "llvm/ADT/ArrayRef.h"
11f26c41e8SKito Cheng #include "llvm/ADT/SmallSet.h"
12f26c41e8SKito Cheng #include "llvm/ADT/StringExtras.h"
13f26c41e8SKito Cheng #include "llvm/ADT/StringSet.h"
14f26c41e8SKito Cheng #include "llvm/ADT/Twine.h"
1506380284SeopXD #include "llvm/Support/ErrorHandling.h"
16f26c41e8SKito Cheng #include "llvm/Support/raw_ostream.h"
17f26c41e8SKito Cheng #include <numeric>
189cf4419eSKazu Hirata #include <optional>
19f26c41e8SKito Cheng 
20f26c41e8SKito Cheng using namespace llvm;
21f26c41e8SKito Cheng 
22f26c41e8SKito Cheng namespace clang {
23f26c41e8SKito Cheng namespace RISCV {
24f26c41e8SKito Cheng 
257ff0bf57SKito Cheng const PrototypeDescriptor PrototypeDescriptor::Mask = PrototypeDescriptor(
267ff0bf57SKito Cheng     BaseTypeModifier::Vector, VectorTypeModifier::MaskVector);
277ff0bf57SKito Cheng const PrototypeDescriptor PrototypeDescriptor::VL =
287ff0bf57SKito Cheng     PrototypeDescriptor(BaseTypeModifier::SizeT);
297ff0bf57SKito Cheng const PrototypeDescriptor PrototypeDescriptor::Vector =
307ff0bf57SKito Cheng     PrototypeDescriptor(BaseTypeModifier::Vector);
317ff0bf57SKito Cheng 
32f26c41e8SKito Cheng //===----------------------------------------------------------------------===//
33f26c41e8SKito Cheng // Type implementation
34f26c41e8SKito Cheng //===----------------------------------------------------------------------===//
35f26c41e8SKito Cheng 
36f26c41e8SKito Cheng LMULType::LMULType(int NewLog2LMUL) {
37f26c41e8SKito Cheng   // Check Log2LMUL is -3, -2, -1, 0, 1, 2, 3
38f26c41e8SKito Cheng   assert(NewLog2LMUL <= 3 && NewLog2LMUL >= -3 && "Bad LMUL number!");
39f26c41e8SKito Cheng   Log2LMUL = NewLog2LMUL;
40f26c41e8SKito Cheng }
41f26c41e8SKito Cheng 
42f26c41e8SKito Cheng std::string LMULType::str() const {
43f26c41e8SKito Cheng   if (Log2LMUL < 0)
44f26c41e8SKito Cheng     return "mf" + utostr(1ULL << (-Log2LMUL));
45f26c41e8SKito Cheng   return "m" + utostr(1ULL << Log2LMUL);
46f26c41e8SKito Cheng }
47f26c41e8SKito Cheng 
48f26c41e8SKito Cheng VScaleVal LMULType::getScale(unsigned ElementBitwidth) const {
49f26c41e8SKito Cheng   int Log2ScaleResult = 0;
50f26c41e8SKito Cheng   switch (ElementBitwidth) {
51f26c41e8SKito Cheng   default:
52f26c41e8SKito Cheng     break;
53f26c41e8SKito Cheng   case 8:
54f26c41e8SKito Cheng     Log2ScaleResult = Log2LMUL + 3;
55f26c41e8SKito Cheng     break;
56f26c41e8SKito Cheng   case 16:
57f26c41e8SKito Cheng     Log2ScaleResult = Log2LMUL + 2;
58f26c41e8SKito Cheng     break;
59f26c41e8SKito Cheng   case 32:
60f26c41e8SKito Cheng     Log2ScaleResult = Log2LMUL + 1;
61f26c41e8SKito Cheng     break;
62f26c41e8SKito Cheng   case 64:
63f26c41e8SKito Cheng     Log2ScaleResult = Log2LMUL;
64f26c41e8SKito Cheng     break;
65f26c41e8SKito Cheng   }
66f26c41e8SKito Cheng   // Illegal vscale result would be less than 1
67f26c41e8SKito Cheng   if (Log2ScaleResult < 0)
685891420eSKazu Hirata     return std::nullopt;
69f26c41e8SKito Cheng   return 1 << Log2ScaleResult;
70f26c41e8SKito Cheng }
71f26c41e8SKito Cheng 
72f26c41e8SKito Cheng void LMULType::MulLog2LMUL(int log2LMUL) { Log2LMUL += log2LMUL; }
73f26c41e8SKito Cheng 
747ff0bf57SKito Cheng RVVType::RVVType(BasicType BT, int Log2LMUL,
757ff0bf57SKito Cheng                  const PrototypeDescriptor &prototype)
76f26c41e8SKito Cheng     : BT(BT), LMUL(LMULType(Log2LMUL)) {
77f26c41e8SKito Cheng   applyBasicType();
78f26c41e8SKito Cheng   applyModifier(prototype);
79f26c41e8SKito Cheng   Valid = verifyType();
80f26c41e8SKito Cheng   if (Valid) {
81f26c41e8SKito Cheng     initBuiltinStr();
82f26c41e8SKito Cheng     initTypeStr();
83f26c41e8SKito Cheng     if (isVector()) {
84f26c41e8SKito Cheng       initClangBuiltinStr();
85f26c41e8SKito Cheng     }
86f26c41e8SKito Cheng   }
87f26c41e8SKito Cheng }
88f26c41e8SKito Cheng 
89f26c41e8SKito Cheng // clang-format off
90f26c41e8SKito Cheng // boolean type are encoded the ratio of n (SEW/LMUL)
91f26c41e8SKito Cheng // SEW/LMUL | 1         | 2         | 4         | 8        | 16        | 32        | 64
92f26c41e8SKito Cheng // c type   | vbool64_t | vbool32_t | vbool16_t | vbool8_t | vbool4_t  | vbool2_t  | vbool1_t
93f26c41e8SKito Cheng // IR type  | nxv1i1    | nxv2i1    | nxv4i1    | nxv8i1   | nxv16i1   | nxv32i1   | nxv64i1
94f26c41e8SKito Cheng 
95f26c41e8SKito Cheng // type\lmul | 1/8    | 1/4      | 1/2     | 1       | 2        | 4        | 8
96f26c41e8SKito Cheng // --------  |------  | -------- | ------- | ------- | -------- | -------- | --------
97f26c41e8SKito Cheng // i64       | N/A    | N/A      | N/A     | nxv1i64 | nxv2i64  | nxv4i64  | nxv8i64
98f26c41e8SKito Cheng // i32       | N/A    | N/A      | nxv1i32 | nxv2i32 | nxv4i32  | nxv8i32  | nxv16i32
99f26c41e8SKito Cheng // i16       | N/A    | nxv1i16  | nxv2i16 | nxv4i16 | nxv8i16  | nxv16i16 | nxv32i16
100f26c41e8SKito Cheng // i8        | nxv1i8 | nxv2i8   | nxv4i8  | nxv8i8  | nxv16i8  | nxv32i8  | nxv64i8
101f26c41e8SKito Cheng // double    | N/A    | N/A      | N/A     | nxv1f64 | nxv2f64  | nxv4f64  | nxv8f64
102f26c41e8SKito Cheng // float     | N/A    | N/A      | nxv1f32 | nxv2f32 | nxv4f32  | nxv8f32  | nxv16f32
103f26c41e8SKito Cheng // half      | N/A    | nxv1f16  | nxv2f16 | nxv4f16 | nxv8f16  | nxv16f16 | nxv32f16
104fbdf6e27SShao-Ce SUN // bfloat16  | N/A    | nxv1bf16 | nxv2bf16| nxv4bf16| nxv8bf16 | nxv16bf16| nxv32bf16
105f26c41e8SKito Cheng // clang-format on
106f26c41e8SKito Cheng 
107f26c41e8SKito Cheng bool RVVType::verifyType() const {
108f26c41e8SKito Cheng   if (ScalarType == Invalid)
109f26c41e8SKito Cheng     return false;
110f26c41e8SKito Cheng   if (isScalar())
111f26c41e8SKito Cheng     return true;
11297afce08SKazu Hirata   if (!Scale)
113f26c41e8SKito Cheng     return false;
114f26c41e8SKito Cheng   if (isFloat() && ElementBitwidth == 8)
115f26c41e8SKito Cheng     return false;
116fbdf6e27SShao-Ce SUN   if (isBFloat() && ElementBitwidth != 16)
117fbdf6e27SShao-Ce SUN     return false;
1180019226cSeopXD   if (IsTuple && (NF == 1 || NF > 8))
1190019226cSeopXD     return false;
1205847ec4dSeopXD   if (IsTuple && (1 << std::max(0, LMUL.Log2LMUL)) * NF > 8)
1215847ec4dSeopXD     return false;
122f4b90773SFangrui Song   unsigned V = *Scale;
123f26c41e8SKito Cheng   switch (ElementBitwidth) {
124f26c41e8SKito Cheng   case 1:
125f26c41e8SKito Cheng   case 8:
126f26c41e8SKito Cheng     // Check Scale is 1,2,4,8,16,32,64
127f26c41e8SKito Cheng     return (V <= 64 && isPowerOf2_32(V));
128f26c41e8SKito Cheng   case 16:
129f26c41e8SKito Cheng     // Check Scale is 1,2,4,8,16,32
130f26c41e8SKito Cheng     return (V <= 32 && isPowerOf2_32(V));
131f26c41e8SKito Cheng   case 32:
132f26c41e8SKito Cheng     // Check Scale is 1,2,4,8,16
133f26c41e8SKito Cheng     return (V <= 16 && isPowerOf2_32(V));
134f26c41e8SKito Cheng   case 64:
135f26c41e8SKito Cheng     // Check Scale is 1,2,4,8
136f26c41e8SKito Cheng     return (V <= 8 && isPowerOf2_32(V));
137f26c41e8SKito Cheng   }
138f26c41e8SKito Cheng   return false;
139f26c41e8SKito Cheng }
140f26c41e8SKito Cheng 
141f26c41e8SKito Cheng void RVVType::initBuiltinStr() {
142f26c41e8SKito Cheng   assert(isValid() && "RVVType is invalid");
143f26c41e8SKito Cheng   switch (ScalarType) {
144f26c41e8SKito Cheng   case ScalarTypeKind::Void:
145f26c41e8SKito Cheng     BuiltinStr = "v";
146f26c41e8SKito Cheng     return;
147f26c41e8SKito Cheng   case ScalarTypeKind::Size_t:
148f26c41e8SKito Cheng     BuiltinStr = "z";
149f26c41e8SKito Cheng     if (IsImmediate)
150f26c41e8SKito Cheng       BuiltinStr = "I" + BuiltinStr;
151f26c41e8SKito Cheng     if (IsPointer)
152f26c41e8SKito Cheng       BuiltinStr += "*";
153f26c41e8SKito Cheng     return;
154f26c41e8SKito Cheng   case ScalarTypeKind::Ptrdiff_t:
155f26c41e8SKito Cheng     BuiltinStr = "Y";
156f26c41e8SKito Cheng     return;
157f26c41e8SKito Cheng   case ScalarTypeKind::UnsignedLong:
158f26c41e8SKito Cheng     BuiltinStr = "ULi";
159f26c41e8SKito Cheng     return;
160f26c41e8SKito Cheng   case ScalarTypeKind::SignedLong:
161f26c41e8SKito Cheng     BuiltinStr = "Li";
162f26c41e8SKito Cheng     return;
163f26c41e8SKito Cheng   case ScalarTypeKind::Boolean:
164f26c41e8SKito Cheng     assert(ElementBitwidth == 1);
165f26c41e8SKito Cheng     BuiltinStr += "b";
166f26c41e8SKito Cheng     break;
167f26c41e8SKito Cheng   case ScalarTypeKind::SignedInteger:
168f26c41e8SKito Cheng   case ScalarTypeKind::UnsignedInteger:
169f26c41e8SKito Cheng     switch (ElementBitwidth) {
170f26c41e8SKito Cheng     case 8:
171f26c41e8SKito Cheng       BuiltinStr += "c";
172f26c41e8SKito Cheng       break;
173f26c41e8SKito Cheng     case 16:
174f26c41e8SKito Cheng       BuiltinStr += "s";
175f26c41e8SKito Cheng       break;
176f26c41e8SKito Cheng     case 32:
177f26c41e8SKito Cheng       BuiltinStr += "i";
178f26c41e8SKito Cheng       break;
179f26c41e8SKito Cheng     case 64:
180f26c41e8SKito Cheng       BuiltinStr += "Wi";
181f26c41e8SKito Cheng       break;
182f26c41e8SKito Cheng     default:
183f26c41e8SKito Cheng       llvm_unreachable("Unhandled ElementBitwidth!");
184f26c41e8SKito Cheng     }
185f26c41e8SKito Cheng     if (isSignedInteger())
186f26c41e8SKito Cheng       BuiltinStr = "S" + BuiltinStr;
187f26c41e8SKito Cheng     else
188f26c41e8SKito Cheng       BuiltinStr = "U" + BuiltinStr;
189f26c41e8SKito Cheng     break;
190f26c41e8SKito Cheng   case ScalarTypeKind::Float:
191f26c41e8SKito Cheng     switch (ElementBitwidth) {
192f26c41e8SKito Cheng     case 16:
193f26c41e8SKito Cheng       BuiltinStr += "x";
194f26c41e8SKito Cheng       break;
195f26c41e8SKito Cheng     case 32:
196f26c41e8SKito Cheng       BuiltinStr += "f";
197f26c41e8SKito Cheng       break;
198f26c41e8SKito Cheng     case 64:
199f26c41e8SKito Cheng       BuiltinStr += "d";
200f26c41e8SKito Cheng       break;
201f26c41e8SKito Cheng     default:
202f26c41e8SKito Cheng       llvm_unreachable("Unhandled ElementBitwidth!");
203f26c41e8SKito Cheng     }
204f26c41e8SKito Cheng     break;
205fbdf6e27SShao-Ce SUN   case ScalarTypeKind::BFloat:
206fa8347fbSMichael Maitland     BuiltinStr += "y";
207fbdf6e27SShao-Ce SUN     break;
208f26c41e8SKito Cheng   default:
209f26c41e8SKito Cheng     llvm_unreachable("ScalarType is invalid!");
210f26c41e8SKito Cheng   }
211f26c41e8SKito Cheng   if (IsImmediate)
212f26c41e8SKito Cheng     BuiltinStr = "I" + BuiltinStr;
213f26c41e8SKito Cheng   if (isScalar()) {
214f26c41e8SKito Cheng     if (IsConstant)
215f26c41e8SKito Cheng       BuiltinStr += "C";
216f26c41e8SKito Cheng     if (IsPointer)
217f26c41e8SKito Cheng       BuiltinStr += "*";
218f26c41e8SKito Cheng     return;
219f26c41e8SKito Cheng   }
220ca4af13eSKazu Hirata   BuiltinStr = "q" + utostr(*Scale) + BuiltinStr;
221f26c41e8SKito Cheng   // Pointer to vector types. Defined for segment load intrinsics.
222f26c41e8SKito Cheng   // segment load intrinsics have pointer type arguments to store the loaded
223f26c41e8SKito Cheng   // vector values.
224f26c41e8SKito Cheng   if (IsPointer)
225f26c41e8SKito Cheng     BuiltinStr += "*";
2260019226cSeopXD 
2270019226cSeopXD   if (IsTuple)
2280019226cSeopXD     BuiltinStr = "T" + utostr(NF) + BuiltinStr;
229f26c41e8SKito Cheng }
230f26c41e8SKito Cheng 
231f26c41e8SKito Cheng void RVVType::initClangBuiltinStr() {
232f26c41e8SKito Cheng   assert(isValid() && "RVVType is invalid");
233f26c41e8SKito Cheng   assert(isVector() && "Handle Vector type only");
234f26c41e8SKito Cheng 
235f26c41e8SKito Cheng   ClangBuiltinStr = "__rvv_";
236f26c41e8SKito Cheng   switch (ScalarType) {
237f26c41e8SKito Cheng   case ScalarTypeKind::Boolean:
238ca4af13eSKazu Hirata     ClangBuiltinStr += "bool" + utostr(64 / *Scale) + "_t";
239f26c41e8SKito Cheng     return;
240f26c41e8SKito Cheng   case ScalarTypeKind::Float:
241f26c41e8SKito Cheng     ClangBuiltinStr += "float";
242f26c41e8SKito Cheng     break;
243fbdf6e27SShao-Ce SUN   case ScalarTypeKind::BFloat:
244fbdf6e27SShao-Ce SUN     ClangBuiltinStr += "bfloat";
245fbdf6e27SShao-Ce SUN     break;
246f26c41e8SKito Cheng   case ScalarTypeKind::SignedInteger:
247f26c41e8SKito Cheng     ClangBuiltinStr += "int";
248f26c41e8SKito Cheng     break;
249f26c41e8SKito Cheng   case ScalarTypeKind::UnsignedInteger:
250f26c41e8SKito Cheng     ClangBuiltinStr += "uint";
251f26c41e8SKito Cheng     break;
252f26c41e8SKito Cheng   default:
253f26c41e8SKito Cheng     llvm_unreachable("ScalarTypeKind is invalid");
254f26c41e8SKito Cheng   }
2550019226cSeopXD   ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.str() +
2560019226cSeopXD                      (IsTuple ? "x" + utostr(NF) : "") + "_t";
257f26c41e8SKito Cheng }
258f26c41e8SKito Cheng 
259f26c41e8SKito Cheng void RVVType::initTypeStr() {
260f26c41e8SKito Cheng   assert(isValid() && "RVVType is invalid");
261f26c41e8SKito Cheng 
262f26c41e8SKito Cheng   if (IsConstant)
263f26c41e8SKito Cheng     Str += "const ";
264f26c41e8SKito Cheng 
265f26c41e8SKito Cheng   auto getTypeString = [&](StringRef TypeStr) {
266f26c41e8SKito Cheng     if (isScalar())
267f26c41e8SKito Cheng       return Twine(TypeStr + Twine(ElementBitwidth) + "_t").str();
2680019226cSeopXD     return Twine("v" + TypeStr + Twine(ElementBitwidth) + LMUL.str() +
2690019226cSeopXD                  (IsTuple ? "x" + utostr(NF) : "") + "_t")
270f26c41e8SKito Cheng         .str();
271f26c41e8SKito Cheng   };
272f26c41e8SKito Cheng 
273f26c41e8SKito Cheng   switch (ScalarType) {
274f26c41e8SKito Cheng   case ScalarTypeKind::Void:
275f26c41e8SKito Cheng     Str = "void";
276f26c41e8SKito Cheng     return;
277f26c41e8SKito Cheng   case ScalarTypeKind::Size_t:
278f26c41e8SKito Cheng     Str = "size_t";
279f26c41e8SKito Cheng     if (IsPointer)
280f26c41e8SKito Cheng       Str += " *";
281f26c41e8SKito Cheng     return;
282f26c41e8SKito Cheng   case ScalarTypeKind::Ptrdiff_t:
283f26c41e8SKito Cheng     Str = "ptrdiff_t";
284f26c41e8SKito Cheng     return;
285f26c41e8SKito Cheng   case ScalarTypeKind::UnsignedLong:
286f26c41e8SKito Cheng     Str = "unsigned long";
287f26c41e8SKito Cheng     return;
288f26c41e8SKito Cheng   case ScalarTypeKind::SignedLong:
289f26c41e8SKito Cheng     Str = "long";
290f26c41e8SKito Cheng     return;
291f26c41e8SKito Cheng   case ScalarTypeKind::Boolean:
292f26c41e8SKito Cheng     if (isScalar())
293f26c41e8SKito Cheng       Str += "bool";
294f26c41e8SKito Cheng     else
295f26c41e8SKito Cheng       // Vector bool is special case, the formulate is
296f26c41e8SKito Cheng       // `vbool<N>_t = MVT::nxv<64/N>i1` ex. vbool16_t = MVT::4i1
297ca4af13eSKazu Hirata       Str += "vbool" + utostr(64 / *Scale) + "_t";
298f26c41e8SKito Cheng     break;
299f26c41e8SKito Cheng   case ScalarTypeKind::Float:
300f26c41e8SKito Cheng     if (isScalar()) {
301f26c41e8SKito Cheng       if (ElementBitwidth == 64)
302f26c41e8SKito Cheng         Str += "double";
303f26c41e8SKito Cheng       else if (ElementBitwidth == 32)
304f26c41e8SKito Cheng         Str += "float";
305f26c41e8SKito Cheng       else if (ElementBitwidth == 16)
306f26c41e8SKito Cheng         Str += "_Float16";
307f26c41e8SKito Cheng       else
308f26c41e8SKito Cheng         llvm_unreachable("Unhandled floating type.");
309f26c41e8SKito Cheng     } else
310f26c41e8SKito Cheng       Str += getTypeString("float");
311f26c41e8SKito Cheng     break;
312fbdf6e27SShao-Ce SUN   case ScalarTypeKind::BFloat:
313fbdf6e27SShao-Ce SUN     if (isScalar()) {
314fbdf6e27SShao-Ce SUN       if (ElementBitwidth == 16)
315fbdf6e27SShao-Ce SUN         Str += "__bf16";
316fbdf6e27SShao-Ce SUN       else
317fbdf6e27SShao-Ce SUN         llvm_unreachable("Unhandled floating type.");
318fbdf6e27SShao-Ce SUN     } else
319fbdf6e27SShao-Ce SUN       Str += getTypeString("bfloat");
320fbdf6e27SShao-Ce SUN     break;
321f26c41e8SKito Cheng   case ScalarTypeKind::SignedInteger:
322f26c41e8SKito Cheng     Str += getTypeString("int");
323f26c41e8SKito Cheng     break;
324f26c41e8SKito Cheng   case ScalarTypeKind::UnsignedInteger:
325f26c41e8SKito Cheng     Str += getTypeString("uint");
326f26c41e8SKito Cheng     break;
327f26c41e8SKito Cheng   default:
328f26c41e8SKito Cheng     llvm_unreachable("ScalarType is invalid!");
329f26c41e8SKito Cheng   }
330f26c41e8SKito Cheng   if (IsPointer)
331f26c41e8SKito Cheng     Str += " *";
332f26c41e8SKito Cheng }
333f26c41e8SKito Cheng 
334f26c41e8SKito Cheng void RVVType::initShortStr() {
335f26c41e8SKito Cheng   switch (ScalarType) {
336f26c41e8SKito Cheng   case ScalarTypeKind::Boolean:
337f26c41e8SKito Cheng     assert(isVector());
338ca4af13eSKazu Hirata     ShortStr = "b" + utostr(64 / *Scale);
339f26c41e8SKito Cheng     return;
340f26c41e8SKito Cheng   case ScalarTypeKind::Float:
341f26c41e8SKito Cheng     ShortStr = "f" + utostr(ElementBitwidth);
342f26c41e8SKito Cheng     break;
343fbdf6e27SShao-Ce SUN   case ScalarTypeKind::BFloat:
344fbdf6e27SShao-Ce SUN     ShortStr = "bf" + utostr(ElementBitwidth);
345fbdf6e27SShao-Ce SUN     break;
346f26c41e8SKito Cheng   case ScalarTypeKind::SignedInteger:
347f26c41e8SKito Cheng     ShortStr = "i" + utostr(ElementBitwidth);
348f26c41e8SKito Cheng     break;
349f26c41e8SKito Cheng   case ScalarTypeKind::UnsignedInteger:
350f26c41e8SKito Cheng     ShortStr = "u" + utostr(ElementBitwidth);
351f26c41e8SKito Cheng     break;
352f26c41e8SKito Cheng   default:
353f26c41e8SKito Cheng     llvm_unreachable("Unhandled case!");
354f26c41e8SKito Cheng   }
355f26c41e8SKito Cheng   if (isVector())
356f26c41e8SKito Cheng     ShortStr += LMUL.str();
3576a097e27SeopXD   if (isTuple())
3586a097e27SeopXD     ShortStr += "x" + utostr(NF);
359f26c41e8SKito Cheng }
360f26c41e8SKito Cheng 
3610e9548bbSeopXD static VectorTypeModifier getTupleVTM(unsigned NF) {
3620e9548bbSeopXD   assert(2 <= NF && NF <= 8 && "2 <= NF <= 8");
3630e9548bbSeopXD   return static_cast<VectorTypeModifier>(
3640e9548bbSeopXD       static_cast<uint8_t>(VectorTypeModifier::Tuple2) + (NF - 2));
3650e9548bbSeopXD }
3660e9548bbSeopXD 
367f26c41e8SKito Cheng void RVVType::applyBasicType() {
368f26c41e8SKito Cheng   switch (BT) {
3697ff0bf57SKito Cheng   case BasicType::Int8:
370f26c41e8SKito Cheng     ElementBitwidth = 8;
371f26c41e8SKito Cheng     ScalarType = ScalarTypeKind::SignedInteger;
372f26c41e8SKito Cheng     break;
3737ff0bf57SKito Cheng   case BasicType::Int16:
374f26c41e8SKito Cheng     ElementBitwidth = 16;
375f26c41e8SKito Cheng     ScalarType = ScalarTypeKind::SignedInteger;
376f26c41e8SKito Cheng     break;
3777ff0bf57SKito Cheng   case BasicType::Int32:
378f26c41e8SKito Cheng     ElementBitwidth = 32;
379f26c41e8SKito Cheng     ScalarType = ScalarTypeKind::SignedInteger;
380f26c41e8SKito Cheng     break;
3817ff0bf57SKito Cheng   case BasicType::Int64:
382f26c41e8SKito Cheng     ElementBitwidth = 64;
383f26c41e8SKito Cheng     ScalarType = ScalarTypeKind::SignedInteger;
384f26c41e8SKito Cheng     break;
3857ff0bf57SKito Cheng   case BasicType::Float16:
386f26c41e8SKito Cheng     ElementBitwidth = 16;
387f26c41e8SKito Cheng     ScalarType = ScalarTypeKind::Float;
388f26c41e8SKito Cheng     break;
3897ff0bf57SKito Cheng   case BasicType::Float32:
390f26c41e8SKito Cheng     ElementBitwidth = 32;
391f26c41e8SKito Cheng     ScalarType = ScalarTypeKind::Float;
392f26c41e8SKito Cheng     break;
3937ff0bf57SKito Cheng   case BasicType::Float64:
394f26c41e8SKito Cheng     ElementBitwidth = 64;
395f26c41e8SKito Cheng     ScalarType = ScalarTypeKind::Float;
396f26c41e8SKito Cheng     break;
397fbdf6e27SShao-Ce SUN   case BasicType::BFloat16:
398fbdf6e27SShao-Ce SUN     ElementBitwidth = 16;
399fbdf6e27SShao-Ce SUN     ScalarType = ScalarTypeKind::BFloat;
400fbdf6e27SShao-Ce SUN     break;
401f26c41e8SKito Cheng   default:
402f26c41e8SKito Cheng     llvm_unreachable("Unhandled type code!");
403f26c41e8SKito Cheng   }
404f26c41e8SKito Cheng   assert(ElementBitwidth != 0 && "Bad element bitwidth!");
405f26c41e8SKito Cheng }
406f26c41e8SKito Cheng 
4079cf4419eSKazu Hirata std::optional<PrototypeDescriptor>
4089cf4419eSKazu Hirata PrototypeDescriptor::parsePrototypeDescriptor(
4097ff0bf57SKito Cheng     llvm::StringRef PrototypeDescriptorStr) {
4107ff0bf57SKito Cheng   PrototypeDescriptor PD;
4117ff0bf57SKito Cheng   BaseTypeModifier PT = BaseTypeModifier::Invalid;
4127ff0bf57SKito Cheng   VectorTypeModifier VTM = VectorTypeModifier::NoModifier;
4137ff0bf57SKito Cheng 
4147ff0bf57SKito Cheng   if (PrototypeDescriptorStr.empty())
4157ff0bf57SKito Cheng     return PD;
4167ff0bf57SKito Cheng 
4177ff0bf57SKito Cheng   // Handle base type modifier
4187ff0bf57SKito Cheng   auto PType = PrototypeDescriptorStr.back();
419f26c41e8SKito Cheng   switch (PType) {
420f26c41e8SKito Cheng   case 'e':
4217ff0bf57SKito Cheng     PT = BaseTypeModifier::Scalar;
422f26c41e8SKito Cheng     break;
423f26c41e8SKito Cheng   case 'v':
4247ff0bf57SKito Cheng     PT = BaseTypeModifier::Vector;
425f26c41e8SKito Cheng     break;
426f26c41e8SKito Cheng   case 'w':
4277ff0bf57SKito Cheng     PT = BaseTypeModifier::Vector;
4287ff0bf57SKito Cheng     VTM = VectorTypeModifier::Widening2XVector;
429f26c41e8SKito Cheng     break;
430f26c41e8SKito Cheng   case 'q':
4317ff0bf57SKito Cheng     PT = BaseTypeModifier::Vector;
4327ff0bf57SKito Cheng     VTM = VectorTypeModifier::Widening4XVector;
433f26c41e8SKito Cheng     break;
434f26c41e8SKito Cheng   case 'o':
4357ff0bf57SKito Cheng     PT = BaseTypeModifier::Vector;
4367ff0bf57SKito Cheng     VTM = VectorTypeModifier::Widening8XVector;
437f26c41e8SKito Cheng     break;
438f26c41e8SKito Cheng   case 'm':
4397ff0bf57SKito Cheng     PT = BaseTypeModifier::Vector;
4407ff0bf57SKito Cheng     VTM = VectorTypeModifier::MaskVector;
441f26c41e8SKito Cheng     break;
442f26c41e8SKito Cheng   case '0':
4437ff0bf57SKito Cheng     PT = BaseTypeModifier::Void;
444f26c41e8SKito Cheng     break;
445f26c41e8SKito Cheng   case 'z':
4467ff0bf57SKito Cheng     PT = BaseTypeModifier::SizeT;
447f26c41e8SKito Cheng     break;
448f26c41e8SKito Cheng   case 't':
4497ff0bf57SKito Cheng     PT = BaseTypeModifier::Ptrdiff;
450f26c41e8SKito Cheng     break;
451f26c41e8SKito Cheng   case 'u':
4527ff0bf57SKito Cheng     PT = BaseTypeModifier::UnsignedLong;
453f26c41e8SKito Cheng     break;
454f26c41e8SKito Cheng   case 'l':
4557ff0bf57SKito Cheng     PT = BaseTypeModifier::SignedLong;
456f26c41e8SKito Cheng     break;
45774f38df1SBrandon Wu   case 'f':
45874f38df1SBrandon Wu     PT = BaseTypeModifier::Float32;
45974f38df1SBrandon Wu     break;
460f26c41e8SKito Cheng   default:
461f26c41e8SKito Cheng     llvm_unreachable("Illegal primitive type transformers!");
462f26c41e8SKito Cheng   }
4637ff0bf57SKito Cheng   PD.PT = static_cast<uint8_t>(PT);
4647ff0bf57SKito Cheng   PrototypeDescriptorStr = PrototypeDescriptorStr.drop_back();
465f26c41e8SKito Cheng 
4667ff0bf57SKito Cheng   // Compute the vector type transformers, it can only appear one time.
467f3dcc235SKazu Hirata   if (PrototypeDescriptorStr.starts_with("(")) {
4687ff0bf57SKito Cheng     assert(VTM == VectorTypeModifier::NoModifier &&
4697ff0bf57SKito Cheng            "VectorTypeModifier should only have one modifier");
4707ff0bf57SKito Cheng     size_t Idx = PrototypeDescriptorStr.find(')');
471f26c41e8SKito Cheng     assert(Idx != StringRef::npos);
4727ff0bf57SKito Cheng     StringRef ComplexType = PrototypeDescriptorStr.slice(1, Idx);
4737ff0bf57SKito Cheng     PrototypeDescriptorStr = PrototypeDescriptorStr.drop_front(Idx + 1);
4747ff0bf57SKito Cheng     assert(!PrototypeDescriptorStr.contains('(') &&
4757ff0bf57SKito Cheng            "Only allow one vector type modifier");
476f26c41e8SKito Cheng 
477f26c41e8SKito Cheng     auto ComplexTT = ComplexType.split(":");
478f26c41e8SKito Cheng     if (ComplexTT.first == "Log2EEW") {
479f26c41e8SKito Cheng       uint32_t Log2EEW;
4807ff0bf57SKito Cheng       if (ComplexTT.second.getAsInteger(10, Log2EEW)) {
4817ff0bf57SKito Cheng         llvm_unreachable("Invalid Log2EEW value!");
4825891420eSKazu Hirata         return std::nullopt;
4837ff0bf57SKito Cheng       }
4847ff0bf57SKito Cheng       switch (Log2EEW) {
4857ff0bf57SKito Cheng       case 3:
4867ff0bf57SKito Cheng         VTM = VectorTypeModifier::Log2EEW3;
4877ff0bf57SKito Cheng         break;
4887ff0bf57SKito Cheng       case 4:
4897ff0bf57SKito Cheng         VTM = VectorTypeModifier::Log2EEW4;
4907ff0bf57SKito Cheng         break;
4917ff0bf57SKito Cheng       case 5:
4927ff0bf57SKito Cheng         VTM = VectorTypeModifier::Log2EEW5;
4937ff0bf57SKito Cheng         break;
4947ff0bf57SKito Cheng       case 6:
4957ff0bf57SKito Cheng         VTM = VectorTypeModifier::Log2EEW6;
4967ff0bf57SKito Cheng         break;
4977ff0bf57SKito Cheng       default:
4987ff0bf57SKito Cheng         llvm_unreachable("Invalid Log2EEW value, should be [3-6]");
4995891420eSKazu Hirata         return std::nullopt;
5007ff0bf57SKito Cheng       }
501f26c41e8SKito Cheng     } else if (ComplexTT.first == "FixedSEW") {
502f26c41e8SKito Cheng       uint32_t NewSEW;
5037ff0bf57SKito Cheng       if (ComplexTT.second.getAsInteger(10, NewSEW)) {
5047ff0bf57SKito Cheng         llvm_unreachable("Invalid FixedSEW value!");
5055891420eSKazu Hirata         return std::nullopt;
506f26c41e8SKito Cheng       }
5077ff0bf57SKito Cheng       switch (NewSEW) {
5087ff0bf57SKito Cheng       case 8:
5097ff0bf57SKito Cheng         VTM = VectorTypeModifier::FixedSEW8;
5107ff0bf57SKito Cheng         break;
5117ff0bf57SKito Cheng       case 16:
5127ff0bf57SKito Cheng         VTM = VectorTypeModifier::FixedSEW16;
5137ff0bf57SKito Cheng         break;
5147ff0bf57SKito Cheng       case 32:
5157ff0bf57SKito Cheng         VTM = VectorTypeModifier::FixedSEW32;
5167ff0bf57SKito Cheng         break;
5177ff0bf57SKito Cheng       case 64:
5187ff0bf57SKito Cheng         VTM = VectorTypeModifier::FixedSEW64;
5197ff0bf57SKito Cheng         break;
5207ff0bf57SKito Cheng       default:
5217ff0bf57SKito Cheng         llvm_unreachable("Invalid FixedSEW value, should be 8, 16, 32 or 64");
5225891420eSKazu Hirata         return std::nullopt;
5237ff0bf57SKito Cheng       }
524f26c41e8SKito Cheng     } else if (ComplexTT.first == "LFixedLog2LMUL") {
5257ff0bf57SKito Cheng       int32_t Log2LMUL;
5267ff0bf57SKito Cheng       if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
5277ff0bf57SKito Cheng         llvm_unreachable("Invalid LFixedLog2LMUL value!");
5285891420eSKazu Hirata         return std::nullopt;
5297ff0bf57SKito Cheng       }
5307ff0bf57SKito Cheng       switch (Log2LMUL) {
5317ff0bf57SKito Cheng       case -3:
5327ff0bf57SKito Cheng         VTM = VectorTypeModifier::LFixedLog2LMULN3;
5337ff0bf57SKito Cheng         break;
5347ff0bf57SKito Cheng       case -2:
5357ff0bf57SKito Cheng         VTM = VectorTypeModifier::LFixedLog2LMULN2;
5367ff0bf57SKito Cheng         break;
5377ff0bf57SKito Cheng       case -1:
5387ff0bf57SKito Cheng         VTM = VectorTypeModifier::LFixedLog2LMULN1;
5397ff0bf57SKito Cheng         break;
5407ff0bf57SKito Cheng       case 0:
5417ff0bf57SKito Cheng         VTM = VectorTypeModifier::LFixedLog2LMUL0;
5427ff0bf57SKito Cheng         break;
5437ff0bf57SKito Cheng       case 1:
5447ff0bf57SKito Cheng         VTM = VectorTypeModifier::LFixedLog2LMUL1;
5457ff0bf57SKito Cheng         break;
5467ff0bf57SKito Cheng       case 2:
5477ff0bf57SKito Cheng         VTM = VectorTypeModifier::LFixedLog2LMUL2;
5487ff0bf57SKito Cheng         break;
5497ff0bf57SKito Cheng       case 3:
5507ff0bf57SKito Cheng         VTM = VectorTypeModifier::LFixedLog2LMUL3;
5517ff0bf57SKito Cheng         break;
5527ff0bf57SKito Cheng       default:
5537ff0bf57SKito Cheng         llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
5545891420eSKazu Hirata         return std::nullopt;
5557ff0bf57SKito Cheng       }
556f26c41e8SKito Cheng     } else if (ComplexTT.first == "SFixedLog2LMUL") {
5577ff0bf57SKito Cheng       int32_t Log2LMUL;
5587ff0bf57SKito Cheng       if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
5597ff0bf57SKito Cheng         llvm_unreachable("Invalid SFixedLog2LMUL value!");
5605891420eSKazu Hirata         return std::nullopt;
5617ff0bf57SKito Cheng       }
5627ff0bf57SKito Cheng       switch (Log2LMUL) {
5637ff0bf57SKito Cheng       case -3:
5647ff0bf57SKito Cheng         VTM = VectorTypeModifier::SFixedLog2LMULN3;
5657ff0bf57SKito Cheng         break;
5667ff0bf57SKito Cheng       case -2:
5677ff0bf57SKito Cheng         VTM = VectorTypeModifier::SFixedLog2LMULN2;
5687ff0bf57SKito Cheng         break;
5697ff0bf57SKito Cheng       case -1:
5707ff0bf57SKito Cheng         VTM = VectorTypeModifier::SFixedLog2LMULN1;
5717ff0bf57SKito Cheng         break;
5727ff0bf57SKito Cheng       case 0:
5737ff0bf57SKito Cheng         VTM = VectorTypeModifier::SFixedLog2LMUL0;
5747ff0bf57SKito Cheng         break;
5757ff0bf57SKito Cheng       case 1:
5767ff0bf57SKito Cheng         VTM = VectorTypeModifier::SFixedLog2LMUL1;
5777ff0bf57SKito Cheng         break;
5787ff0bf57SKito Cheng       case 2:
5797ff0bf57SKito Cheng         VTM = VectorTypeModifier::SFixedLog2LMUL2;
5807ff0bf57SKito Cheng         break;
5817ff0bf57SKito Cheng       case 3:
5827ff0bf57SKito Cheng         VTM = VectorTypeModifier::SFixedLog2LMUL3;
5837ff0bf57SKito Cheng         break;
5847ff0bf57SKito Cheng       default:
5857ff0bf57SKito Cheng         llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
5865891420eSKazu Hirata         return std::nullopt;
5877ff0bf57SKito Cheng       }
5887ff0bf57SKito Cheng 
5892a05a521S4vtomat     } else if (ComplexTT.first == "SEFixedLog2LMUL") {
5902a05a521S4vtomat       int32_t Log2LMUL;
5912a05a521S4vtomat       if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
5922a05a521S4vtomat         llvm_unreachable("Invalid SEFixedLog2LMUL value!");
5932a05a521S4vtomat         return std::nullopt;
5942a05a521S4vtomat       }
5952a05a521S4vtomat       switch (Log2LMUL) {
5962a05a521S4vtomat       case -3:
5972a05a521S4vtomat         VTM = VectorTypeModifier::SEFixedLog2LMULN3;
5982a05a521S4vtomat         break;
5992a05a521S4vtomat       case -2:
6002a05a521S4vtomat         VTM = VectorTypeModifier::SEFixedLog2LMULN2;
6012a05a521S4vtomat         break;
6022a05a521S4vtomat       case -1:
6032a05a521S4vtomat         VTM = VectorTypeModifier::SEFixedLog2LMULN1;
6042a05a521S4vtomat         break;
6052a05a521S4vtomat       case 0:
6062a05a521S4vtomat         VTM = VectorTypeModifier::SEFixedLog2LMUL0;
6072a05a521S4vtomat         break;
6082a05a521S4vtomat       case 1:
6092a05a521S4vtomat         VTM = VectorTypeModifier::SEFixedLog2LMUL1;
6102a05a521S4vtomat         break;
6112a05a521S4vtomat       case 2:
6122a05a521S4vtomat         VTM = VectorTypeModifier::SEFixedLog2LMUL2;
6132a05a521S4vtomat         break;
6142a05a521S4vtomat       case 3:
6152a05a521S4vtomat         VTM = VectorTypeModifier::SEFixedLog2LMUL3;
6162a05a521S4vtomat         break;
6172a05a521S4vtomat       default:
6182a05a521S4vtomat         llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
6192a05a521S4vtomat         return std::nullopt;
6202a05a521S4vtomat       }
6210019226cSeopXD     } else if (ComplexTT.first == "Tuple") {
6220019226cSeopXD       unsigned NF = 0;
6230019226cSeopXD       if (ComplexTT.second.getAsInteger(10, NF)) {
6240019226cSeopXD         llvm_unreachable("Invalid NF value!");
6250019226cSeopXD         return std::nullopt;
6260019226cSeopXD       }
6270e9548bbSeopXD       VTM = getTupleVTM(NF);
628f26c41e8SKito Cheng     } else {
629f26c41e8SKito Cheng       llvm_unreachable("Illegal complex type transformers!");
630f26c41e8SKito Cheng     }
631f26c41e8SKito Cheng   }
6327ff0bf57SKito Cheng   PD.VTM = static_cast<uint8_t>(VTM);
633f26c41e8SKito Cheng 
634f26c41e8SKito Cheng   // Compute the remain type transformers
6357ff0bf57SKito Cheng   TypeModifier TM = TypeModifier::NoModifier;
6367ff0bf57SKito Cheng   for (char I : PrototypeDescriptorStr) {
637f26c41e8SKito Cheng     switch (I) {
638f26c41e8SKito Cheng     case 'P':
6397ff0bf57SKito Cheng       if ((TM & TypeModifier::Const) == TypeModifier::Const)
640f26c41e8SKito Cheng         llvm_unreachable("'P' transformer cannot be used after 'C'");
6417ff0bf57SKito Cheng       if ((TM & TypeModifier::Pointer) == TypeModifier::Pointer)
642f26c41e8SKito Cheng         llvm_unreachable("'P' transformer cannot be used twice");
6437ff0bf57SKito Cheng       TM |= TypeModifier::Pointer;
644f26c41e8SKito Cheng       break;
645f26c41e8SKito Cheng     case 'C':
6467ff0bf57SKito Cheng       TM |= TypeModifier::Const;
647f26c41e8SKito Cheng       break;
648f26c41e8SKito Cheng     case 'K':
6497ff0bf57SKito Cheng       TM |= TypeModifier::Immediate;
650f26c41e8SKito Cheng       break;
651f26c41e8SKito Cheng     case 'U':
6527ff0bf57SKito Cheng       TM |= TypeModifier::UnsignedInteger;
653f26c41e8SKito Cheng       break;
654f26c41e8SKito Cheng     case 'I':
6557ff0bf57SKito Cheng       TM |= TypeModifier::SignedInteger;
656f26c41e8SKito Cheng       break;
657f26c41e8SKito Cheng     case 'F':
6587ff0bf57SKito Cheng       TM |= TypeModifier::Float;
659f26c41e8SKito Cheng       break;
660f26c41e8SKito Cheng     case 'S':
6617ff0bf57SKito Cheng       TM |= TypeModifier::LMUL1;
662f26c41e8SKito Cheng       break;
663f26c41e8SKito Cheng     default:
664f26c41e8SKito Cheng       llvm_unreachable("Illegal non-primitive type transformer!");
665f26c41e8SKito Cheng     }
666f26c41e8SKito Cheng   }
6677ff0bf57SKito Cheng   PD.TM = static_cast<uint8_t>(TM);
6687ff0bf57SKito Cheng 
6697ff0bf57SKito Cheng   return PD;
6707ff0bf57SKito Cheng }
6717ff0bf57SKito Cheng 
6727ff0bf57SKito Cheng void RVVType::applyModifier(const PrototypeDescriptor &Transformer) {
6737ff0bf57SKito Cheng   // Handle primitive type transformer
6747ff0bf57SKito Cheng   switch (static_cast<BaseTypeModifier>(Transformer.PT)) {
6757ff0bf57SKito Cheng   case BaseTypeModifier::Scalar:
6767ff0bf57SKito Cheng     Scale = 0;
6777ff0bf57SKito Cheng     break;
6787ff0bf57SKito Cheng   case BaseTypeModifier::Vector:
6797ff0bf57SKito Cheng     Scale = LMUL.getScale(ElementBitwidth);
6807ff0bf57SKito Cheng     break;
6817ff0bf57SKito Cheng   case BaseTypeModifier::Void:
6827ff0bf57SKito Cheng     ScalarType = ScalarTypeKind::Void;
6837ff0bf57SKito Cheng     break;
6847ff0bf57SKito Cheng   case BaseTypeModifier::SizeT:
6857ff0bf57SKito Cheng     ScalarType = ScalarTypeKind::Size_t;
6867ff0bf57SKito Cheng     break;
6877ff0bf57SKito Cheng   case BaseTypeModifier::Ptrdiff:
6887ff0bf57SKito Cheng     ScalarType = ScalarTypeKind::Ptrdiff_t;
6897ff0bf57SKito Cheng     break;
6907ff0bf57SKito Cheng   case BaseTypeModifier::UnsignedLong:
6917ff0bf57SKito Cheng     ScalarType = ScalarTypeKind::UnsignedLong;
6927ff0bf57SKito Cheng     break;
6937ff0bf57SKito Cheng   case BaseTypeModifier::SignedLong:
6947ff0bf57SKito Cheng     ScalarType = ScalarTypeKind::SignedLong;
6957ff0bf57SKito Cheng     break;
69674f38df1SBrandon Wu   case BaseTypeModifier::Float32:
69774f38df1SBrandon Wu     ElementBitwidth = 32;
69874f38df1SBrandon Wu     ScalarType = ScalarTypeKind::Float;
69974f38df1SBrandon Wu     break;
7007ff0bf57SKito Cheng   case BaseTypeModifier::Invalid:
7017ff0bf57SKito Cheng     ScalarType = ScalarTypeKind::Invalid;
7027ff0bf57SKito Cheng     return;
7037ff0bf57SKito Cheng   }
7047ff0bf57SKito Cheng 
7057ff0bf57SKito Cheng   switch (static_cast<VectorTypeModifier>(Transformer.VTM)) {
7067ff0bf57SKito Cheng   case VectorTypeModifier::Widening2XVector:
7077ff0bf57SKito Cheng     ElementBitwidth *= 2;
708da201aa4SeopXD     LMUL.MulLog2LMUL(1);
7097ff0bf57SKito Cheng     Scale = LMUL.getScale(ElementBitwidth);
7107ff0bf57SKito Cheng     break;
7117ff0bf57SKito Cheng   case VectorTypeModifier::Widening4XVector:
7127ff0bf57SKito Cheng     ElementBitwidth *= 4;
713da201aa4SeopXD     LMUL.MulLog2LMUL(2);
7147ff0bf57SKito Cheng     Scale = LMUL.getScale(ElementBitwidth);
7157ff0bf57SKito Cheng     break;
7167ff0bf57SKito Cheng   case VectorTypeModifier::Widening8XVector:
7177ff0bf57SKito Cheng     ElementBitwidth *= 8;
718da201aa4SeopXD     LMUL.MulLog2LMUL(3);
7197ff0bf57SKito Cheng     Scale = LMUL.getScale(ElementBitwidth);
7207ff0bf57SKito Cheng     break;
7217ff0bf57SKito Cheng   case VectorTypeModifier::MaskVector:
7227ff0bf57SKito Cheng     ScalarType = ScalarTypeKind::Boolean;
7237ff0bf57SKito Cheng     Scale = LMUL.getScale(ElementBitwidth);
7247ff0bf57SKito Cheng     ElementBitwidth = 1;
7257ff0bf57SKito Cheng     break;
7267ff0bf57SKito Cheng   case VectorTypeModifier::Log2EEW3:
7277ff0bf57SKito Cheng     applyLog2EEW(3);
7287ff0bf57SKito Cheng     break;
7297ff0bf57SKito Cheng   case VectorTypeModifier::Log2EEW4:
7307ff0bf57SKito Cheng     applyLog2EEW(4);
7317ff0bf57SKito Cheng     break;
7327ff0bf57SKito Cheng   case VectorTypeModifier::Log2EEW5:
7337ff0bf57SKito Cheng     applyLog2EEW(5);
7347ff0bf57SKito Cheng     break;
7357ff0bf57SKito Cheng   case VectorTypeModifier::Log2EEW6:
7367ff0bf57SKito Cheng     applyLog2EEW(6);
7377ff0bf57SKito Cheng     break;
7387ff0bf57SKito Cheng   case VectorTypeModifier::FixedSEW8:
7397ff0bf57SKito Cheng     applyFixedSEW(8);
7407ff0bf57SKito Cheng     break;
7417ff0bf57SKito Cheng   case VectorTypeModifier::FixedSEW16:
7427ff0bf57SKito Cheng     applyFixedSEW(16);
7437ff0bf57SKito Cheng     break;
7447ff0bf57SKito Cheng   case VectorTypeModifier::FixedSEW32:
7457ff0bf57SKito Cheng     applyFixedSEW(32);
7467ff0bf57SKito Cheng     break;
7477ff0bf57SKito Cheng   case VectorTypeModifier::FixedSEW64:
7487ff0bf57SKito Cheng     applyFixedSEW(64);
7497ff0bf57SKito Cheng     break;
7507ff0bf57SKito Cheng   case VectorTypeModifier::LFixedLog2LMULN3:
7517ff0bf57SKito Cheng     applyFixedLog2LMUL(-3, FixedLMULType::LargerThan);
7527ff0bf57SKito Cheng     break;
7537ff0bf57SKito Cheng   case VectorTypeModifier::LFixedLog2LMULN2:
7547ff0bf57SKito Cheng     applyFixedLog2LMUL(-2, FixedLMULType::LargerThan);
7557ff0bf57SKito Cheng     break;
7567ff0bf57SKito Cheng   case VectorTypeModifier::LFixedLog2LMULN1:
7577ff0bf57SKito Cheng     applyFixedLog2LMUL(-1, FixedLMULType::LargerThan);
7587ff0bf57SKito Cheng     break;
7597ff0bf57SKito Cheng   case VectorTypeModifier::LFixedLog2LMUL0:
7607ff0bf57SKito Cheng     applyFixedLog2LMUL(0, FixedLMULType::LargerThan);
7617ff0bf57SKito Cheng     break;
7627ff0bf57SKito Cheng   case VectorTypeModifier::LFixedLog2LMUL1:
7637ff0bf57SKito Cheng     applyFixedLog2LMUL(1, FixedLMULType::LargerThan);
7647ff0bf57SKito Cheng     break;
7657ff0bf57SKito Cheng   case VectorTypeModifier::LFixedLog2LMUL2:
7667ff0bf57SKito Cheng     applyFixedLog2LMUL(2, FixedLMULType::LargerThan);
7677ff0bf57SKito Cheng     break;
7687ff0bf57SKito Cheng   case VectorTypeModifier::LFixedLog2LMUL3:
7697ff0bf57SKito Cheng     applyFixedLog2LMUL(3, FixedLMULType::LargerThan);
7707ff0bf57SKito Cheng     break;
7717ff0bf57SKito Cheng   case VectorTypeModifier::SFixedLog2LMULN3:
7727ff0bf57SKito Cheng     applyFixedLog2LMUL(-3, FixedLMULType::SmallerThan);
7737ff0bf57SKito Cheng     break;
7747ff0bf57SKito Cheng   case VectorTypeModifier::SFixedLog2LMULN2:
7757ff0bf57SKito Cheng     applyFixedLog2LMUL(-2, FixedLMULType::SmallerThan);
7767ff0bf57SKito Cheng     break;
7777ff0bf57SKito Cheng   case VectorTypeModifier::SFixedLog2LMULN1:
7787ff0bf57SKito Cheng     applyFixedLog2LMUL(-1, FixedLMULType::SmallerThan);
7797ff0bf57SKito Cheng     break;
7807ff0bf57SKito Cheng   case VectorTypeModifier::SFixedLog2LMUL0:
7817ff0bf57SKito Cheng     applyFixedLog2LMUL(0, FixedLMULType::SmallerThan);
7827ff0bf57SKito Cheng     break;
7837ff0bf57SKito Cheng   case VectorTypeModifier::SFixedLog2LMUL1:
7847ff0bf57SKito Cheng     applyFixedLog2LMUL(1, FixedLMULType::SmallerThan);
7857ff0bf57SKito Cheng     break;
7867ff0bf57SKito Cheng   case VectorTypeModifier::SFixedLog2LMUL2:
7877ff0bf57SKito Cheng     applyFixedLog2LMUL(2, FixedLMULType::SmallerThan);
7887ff0bf57SKito Cheng     break;
7897ff0bf57SKito Cheng   case VectorTypeModifier::SFixedLog2LMUL3:
7907ff0bf57SKito Cheng     applyFixedLog2LMUL(3, FixedLMULType::SmallerThan);
7917ff0bf57SKito Cheng     break;
7922a05a521S4vtomat   case VectorTypeModifier::SEFixedLog2LMULN3:
7932a05a521S4vtomat     applyFixedLog2LMUL(-3, FixedLMULType::SmallerOrEqual);
7942a05a521S4vtomat     break;
7952a05a521S4vtomat   case VectorTypeModifier::SEFixedLog2LMULN2:
7962a05a521S4vtomat     applyFixedLog2LMUL(-2, FixedLMULType::SmallerOrEqual);
7972a05a521S4vtomat     break;
7982a05a521S4vtomat   case VectorTypeModifier::SEFixedLog2LMULN1:
7992a05a521S4vtomat     applyFixedLog2LMUL(-1, FixedLMULType::SmallerOrEqual);
8002a05a521S4vtomat     break;
8012a05a521S4vtomat   case VectorTypeModifier::SEFixedLog2LMUL0:
8022a05a521S4vtomat     applyFixedLog2LMUL(0, FixedLMULType::SmallerOrEqual);
8032a05a521S4vtomat     break;
8042a05a521S4vtomat   case VectorTypeModifier::SEFixedLog2LMUL1:
8052a05a521S4vtomat     applyFixedLog2LMUL(1, FixedLMULType::SmallerOrEqual);
8062a05a521S4vtomat     break;
8072a05a521S4vtomat   case VectorTypeModifier::SEFixedLog2LMUL2:
8082a05a521S4vtomat     applyFixedLog2LMUL(2, FixedLMULType::SmallerOrEqual);
8092a05a521S4vtomat     break;
8102a05a521S4vtomat   case VectorTypeModifier::SEFixedLog2LMUL3:
8112a05a521S4vtomat     applyFixedLog2LMUL(3, FixedLMULType::SmallerOrEqual);
8122a05a521S4vtomat     break;
8135847ec4dSeopXD   case VectorTypeModifier::Tuple2:
8145847ec4dSeopXD   case VectorTypeModifier::Tuple3:
8155847ec4dSeopXD   case VectorTypeModifier::Tuple4:
8165847ec4dSeopXD   case VectorTypeModifier::Tuple5:
8175847ec4dSeopXD   case VectorTypeModifier::Tuple6:
8185847ec4dSeopXD   case VectorTypeModifier::Tuple7:
8195847ec4dSeopXD   case VectorTypeModifier::Tuple8: {
8200019226cSeopXD     IsTuple = true;
8215847ec4dSeopXD     NF = 2 + static_cast<uint8_t>(Transformer.VTM) -
8225847ec4dSeopXD          static_cast<uint8_t>(VectorTypeModifier::Tuple2);
8230019226cSeopXD     break;
8240019226cSeopXD   }
8257ff0bf57SKito Cheng   case VectorTypeModifier::NoModifier:
8267ff0bf57SKito Cheng     break;
8277ff0bf57SKito Cheng   }
8287ff0bf57SKito Cheng 
829f3ce9250S4vtomat   // Early return if the current type modifier is already invalid.
830f3ce9250S4vtomat   if (ScalarType == Invalid)
831f3ce9250S4vtomat     return;
832f3ce9250S4vtomat 
8337ff0bf57SKito Cheng   for (unsigned TypeModifierMaskShift = 0;
8347ff0bf57SKito Cheng        TypeModifierMaskShift <= static_cast<unsigned>(TypeModifier::MaxOffset);
8357ff0bf57SKito Cheng        ++TypeModifierMaskShift) {
8367ff0bf57SKito Cheng     unsigned TypeModifierMask = 1 << TypeModifierMaskShift;
8377ff0bf57SKito Cheng     if ((static_cast<unsigned>(Transformer.TM) & TypeModifierMask) !=
8387ff0bf57SKito Cheng         TypeModifierMask)
8397ff0bf57SKito Cheng       continue;
8407ff0bf57SKito Cheng     switch (static_cast<TypeModifier>(TypeModifierMask)) {
8417ff0bf57SKito Cheng     case TypeModifier::Pointer:
8427ff0bf57SKito Cheng       IsPointer = true;
8437ff0bf57SKito Cheng       break;
8447ff0bf57SKito Cheng     case TypeModifier::Const:
8457ff0bf57SKito Cheng       IsConstant = true;
8467ff0bf57SKito Cheng       break;
8477ff0bf57SKito Cheng     case TypeModifier::Immediate:
8487ff0bf57SKito Cheng       IsImmediate = true;
8497ff0bf57SKito Cheng       IsConstant = true;
8507ff0bf57SKito Cheng       break;
8517ff0bf57SKito Cheng     case TypeModifier::UnsignedInteger:
8527ff0bf57SKito Cheng       ScalarType = ScalarTypeKind::UnsignedInteger;
8537ff0bf57SKito Cheng       break;
8547ff0bf57SKito Cheng     case TypeModifier::SignedInteger:
8557ff0bf57SKito Cheng       ScalarType = ScalarTypeKind::SignedInteger;
8567ff0bf57SKito Cheng       break;
8577ff0bf57SKito Cheng     case TypeModifier::Float:
8587ff0bf57SKito Cheng       ScalarType = ScalarTypeKind::Float;
8597ff0bf57SKito Cheng       break;
8601c937819SYueh-Ting (eop) Chen     case TypeModifier::BFloat:
8611c937819SYueh-Ting (eop) Chen       ScalarType = ScalarTypeKind::BFloat;
8621c937819SYueh-Ting (eop) Chen       break;
8637ff0bf57SKito Cheng     case TypeModifier::LMUL1:
8647ff0bf57SKito Cheng       LMUL = LMULType(0);
8657ff0bf57SKito Cheng       // Update ElementBitwidth need to update Scale too.
8667ff0bf57SKito Cheng       Scale = LMUL.getScale(ElementBitwidth);
8677ff0bf57SKito Cheng       break;
8687ff0bf57SKito Cheng     default:
8697ff0bf57SKito Cheng       llvm_unreachable("Unknown type modifier mask!");
8707ff0bf57SKito Cheng     }
8717ff0bf57SKito Cheng   }
8727ff0bf57SKito Cheng }
8737ff0bf57SKito Cheng 
8747ff0bf57SKito Cheng void RVVType::applyLog2EEW(unsigned Log2EEW) {
8757ff0bf57SKito Cheng   // update new elmul = (eew/sew) * lmul
8767ff0bf57SKito Cheng   LMUL.MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth));
8777ff0bf57SKito Cheng   // update new eew
8787ff0bf57SKito Cheng   ElementBitwidth = 1 << Log2EEW;
8797ff0bf57SKito Cheng   ScalarType = ScalarTypeKind::SignedInteger;
8807ff0bf57SKito Cheng   Scale = LMUL.getScale(ElementBitwidth);
8817ff0bf57SKito Cheng }
8827ff0bf57SKito Cheng 
8837ff0bf57SKito Cheng void RVVType::applyFixedSEW(unsigned NewSEW) {
8847ff0bf57SKito Cheng   // Set invalid type if src and dst SEW are same.
8857ff0bf57SKito Cheng   if (ElementBitwidth == NewSEW) {
8867ff0bf57SKito Cheng     ScalarType = ScalarTypeKind::Invalid;
8877ff0bf57SKito Cheng     return;
8887ff0bf57SKito Cheng   }
8897ff0bf57SKito Cheng   // Update new SEW
8907ff0bf57SKito Cheng   ElementBitwidth = NewSEW;
8917ff0bf57SKito Cheng   Scale = LMUL.getScale(ElementBitwidth);
8927ff0bf57SKito Cheng }
8937ff0bf57SKito Cheng 
8947ff0bf57SKito Cheng void RVVType::applyFixedLog2LMUL(int Log2LMUL, enum FixedLMULType Type) {
8957ff0bf57SKito Cheng   switch (Type) {
8967ff0bf57SKito Cheng   case FixedLMULType::LargerThan:
897f3ce9250S4vtomat     if (Log2LMUL <= LMUL.Log2LMUL) {
8987ff0bf57SKito Cheng       ScalarType = ScalarTypeKind::Invalid;
8997ff0bf57SKito Cheng       return;
9007ff0bf57SKito Cheng     }
9017ff0bf57SKito Cheng     break;
9027ff0bf57SKito Cheng   case FixedLMULType::SmallerThan:
903f3ce9250S4vtomat     if (Log2LMUL >= LMUL.Log2LMUL) {
9047ff0bf57SKito Cheng       ScalarType = ScalarTypeKind::Invalid;
9057ff0bf57SKito Cheng       return;
9067ff0bf57SKito Cheng     }
9077ff0bf57SKito Cheng     break;
9082a05a521S4vtomat   case FixedLMULType::SmallerOrEqual:
9092a05a521S4vtomat     if (Log2LMUL > LMUL.Log2LMUL) {
9102a05a521S4vtomat       ScalarType = ScalarTypeKind::Invalid;
9112a05a521S4vtomat       return;
9122a05a521S4vtomat     }
9132a05a521S4vtomat     break;
9147ff0bf57SKito Cheng   }
9157ff0bf57SKito Cheng 
9167ff0bf57SKito Cheng   // Update new LMUL
9177ff0bf57SKito Cheng   LMUL = LMULType(Log2LMUL);
9187ff0bf57SKito Cheng   Scale = LMUL.getScale(ElementBitwidth);
9197ff0bf57SKito Cheng }
9207ff0bf57SKito Cheng 
9219cf4419eSKazu Hirata std::optional<RVVTypes>
9223fe89be8SKito Cheng RVVTypeCache::computeTypes(BasicType BT, int Log2LMUL, unsigned NF,
92379e3d57fSZakk Chen                            ArrayRef<PrototypeDescriptor> Prototype) {
9247ff0bf57SKito Cheng   RVVTypes Types;
92579e3d57fSZakk Chen   for (const PrototypeDescriptor &Proto : Prototype) {
9267ff0bf57SKito Cheng     auto T = computeType(BT, Log2LMUL, Proto);
92797afce08SKazu Hirata     if (!T)
9285891420eSKazu Hirata       return std::nullopt;
9297ff0bf57SKito Cheng     // Record legal type index
930fc6ca0d0SFangrui Song     Types.push_back(*T);
9317ff0bf57SKito Cheng   }
9327ff0bf57SKito Cheng   return Types;
9337ff0bf57SKito Cheng }
9347ff0bf57SKito Cheng 
9357ff0bf57SKito Cheng // Compute the hash value of RVVType, used for cache the result of computeType.
9367ff0bf57SKito Cheng static uint64_t computeRVVTypeHashValue(BasicType BT, int Log2LMUL,
9377ff0bf57SKito Cheng                                         PrototypeDescriptor Proto) {
9387ff0bf57SKito Cheng   // Layout of hash value:
9397ff0bf57SKito Cheng   // 0               8    16          24        32          40
9407ff0bf57SKito Cheng   // | Log2LMUL + 3  | BT  | Proto.PT | Proto.TM | Proto.VTM |
9417ff0bf57SKito Cheng   assert(Log2LMUL >= -3 && Log2LMUL <= 3);
9427ff0bf57SKito Cheng   return (Log2LMUL + 3) | (static_cast<uint64_t>(BT) & 0xff) << 8 |
9437ff0bf57SKito Cheng          ((uint64_t)(Proto.PT & 0xff) << 16) |
9447ff0bf57SKito Cheng          ((uint64_t)(Proto.TM & 0xff) << 24) |
9457ff0bf57SKito Cheng          ((uint64_t)(Proto.VTM & 0xff) << 32);
9467ff0bf57SKito Cheng }
9477ff0bf57SKito Cheng 
9489cf4419eSKazu Hirata std::optional<RVVTypePtr> RVVTypeCache::computeType(BasicType BT, int Log2LMUL,
9497ff0bf57SKito Cheng                                                     PrototypeDescriptor Proto) {
9507ff0bf57SKito Cheng   uint64_t Idx = computeRVVTypeHashValue(BT, Log2LMUL, Proto);
9517ff0bf57SKito Cheng   // Search first
9527ff0bf57SKito Cheng   auto It = LegalTypes.find(Idx);
9537ff0bf57SKito Cheng   if (It != LegalTypes.end())
9547ff0bf57SKito Cheng     return &(It->second);
9557ff0bf57SKito Cheng 
9567ff0bf57SKito Cheng   if (IllegalTypes.count(Idx))
9575891420eSKazu Hirata     return std::nullopt;
9587ff0bf57SKito Cheng 
9597ff0bf57SKito Cheng   // Compute type and record the result.
9607ff0bf57SKito Cheng   RVVType T(BT, Log2LMUL, Proto);
9617ff0bf57SKito Cheng   if (T.isValid()) {
9627ff0bf57SKito Cheng     // Record legal type index and value.
9633fe89be8SKito Cheng     std::pair<std::unordered_map<uint64_t, RVVType>::iterator, bool>
9643fe89be8SKito Cheng         InsertResult = LegalTypes.insert({Idx, T});
9653fe89be8SKito Cheng     return &(InsertResult.first->second);
9667ff0bf57SKito Cheng   }
9677ff0bf57SKito Cheng   // Record illegal type index.
9687ff0bf57SKito Cheng   IllegalTypes.insert(Idx);
9695891420eSKazu Hirata   return std::nullopt;
970f26c41e8SKito Cheng }
971f26c41e8SKito Cheng 
972f26c41e8SKito Cheng //===----------------------------------------------------------------------===//
973f26c41e8SKito Cheng // RVVIntrinsic implementation
974f26c41e8SKito Cheng //===----------------------------------------------------------------------===//
97576482078SeopXD RVVIntrinsic::RVVIntrinsic(
97676482078SeopXD     StringRef NewName, StringRef Suffix, StringRef NewOverloadedName,
97776482078SeopXD     StringRef OverloadedSuffix, StringRef IRName, bool IsMasked,
97876482078SeopXD     bool HasMaskedOffOperand, bool HasVL, PolicyScheme Scheme,
97976482078SeopXD     bool SupportOverloading, bool HasBuiltinAlias, StringRef ManualCodegen,
98076482078SeopXD     const RVVTypes &OutInTypes, const std::vector<int64_t> &NewIntrinsicTypes,
98184741940SCraig Topper     unsigned NF, Policy NewPolicyAttrs, bool HasFRMRoundModeOp)
98271fd6616SZakk Chen     : IRName(IRName), IsMasked(IsMasked),
98371fd6616SZakk Chen       HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme),
98471fd6616SZakk Chen       SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias),
985405889ebSJie Fu       ManualCodegen(ManualCodegen.str()), NF(NF), PolicyAttrs(NewPolicyAttrs) {
986f26c41e8SKito Cheng 
98779e3d57fSZakk Chen   // Init BuiltinName, Name and OverloadedName
988f26c41e8SKito Cheng   BuiltinName = NewName.str();
989f26c41e8SKito Cheng   Name = BuiltinName;
99079e3d57fSZakk Chen   if (NewOverloadedName.empty())
99179e3d57fSZakk Chen     OverloadedName = NewName.split("_").first.str();
992f26c41e8SKito Cheng   else
99379e3d57fSZakk Chen     OverloadedName = NewOverloadedName.str();
994f26c41e8SKito Cheng   if (!Suffix.empty())
995f26c41e8SKito Cheng     Name += "_" + Suffix.str();
99679e3d57fSZakk Chen   if (!OverloadedSuffix.empty())
99779e3d57fSZakk Chen     OverloadedName += "_" + OverloadedSuffix.str();
99871fd6616SZakk Chen 
9996b282294SeopXD   updateNamesAndPolicy(IsMasked, hasPolicy(), Name, BuiltinName, OverloadedName,
100076482078SeopXD                        PolicyAttrs, HasFRMRoundModeOp);
1001f26c41e8SKito Cheng 
1002f26c41e8SKito Cheng   // Init OutputType and InputTypes
1003f26c41e8SKito Cheng   OutputType = OutInTypes[0];
1004f26c41e8SKito Cheng   InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
1005f26c41e8SKito Cheng 
1006f26c41e8SKito Cheng   // IntrinsicTypes is unmasked TA version index. Need to update it
1007f26c41e8SKito Cheng   // if there is merge operand (It is always in first operand).
1008f26c41e8SKito Cheng   IntrinsicTypes = NewIntrinsicTypes;
100971fd6616SZakk Chen   if ((IsMasked && hasMaskedOffOperand()) ||
10106b282294SeopXD       (!IsMasked && hasPassthruOperand())) {
1011f26c41e8SKito Cheng     for (auto &I : IntrinsicTypes) {
1012f26c41e8SKito Cheng       if (I >= 0)
1013*239127d7SBrandon Wu         I += 1;
1014f26c41e8SKito Cheng     }
1015f26c41e8SKito Cheng   }
1016f26c41e8SKito Cheng }
1017f26c41e8SKito Cheng 
1018f26c41e8SKito Cheng std::string RVVIntrinsic::getBuiltinTypeStr() const {
1019f26c41e8SKito Cheng   std::string S;
1020f26c41e8SKito Cheng   S += OutputType->getBuiltinStr();
1021f26c41e8SKito Cheng   for (const auto &T : InputTypes) {
1022f26c41e8SKito Cheng     S += T->getBuiltinStr();
1023f26c41e8SKito Cheng   }
1024f26c41e8SKito Cheng   return S;
1025f26c41e8SKito Cheng }
1026f26c41e8SKito Cheng 
10277ff0bf57SKito Cheng std::string RVVIntrinsic::getSuffixStr(
10283fe89be8SKito Cheng     RVVTypeCache &TypeCache, BasicType Type, int Log2LMUL,
1029b166aa83SKito Cheng     llvm::ArrayRef<PrototypeDescriptor> PrototypeDescriptors) {
10307ff0bf57SKito Cheng   SmallVector<std::string> SuffixStrs;
10317ff0bf57SKito Cheng   for (auto PD : PrototypeDescriptors) {
10323fe89be8SKito Cheng     auto T = TypeCache.computeType(Type, Log2LMUL, PD);
1033ca4af13eSKazu Hirata     SuffixStrs.push_back((*T)->getShortStr());
10347ff0bf57SKito Cheng   }
10357ff0bf57SKito Cheng   return join(SuffixStrs, "_");
10367ff0bf57SKito Cheng }
10377ff0bf57SKito Cheng 
103871fd6616SZakk Chen llvm::SmallVector<PrototypeDescriptor> RVVIntrinsic::computeBuiltinTypes(
103971fd6616SZakk Chen     llvm::ArrayRef<PrototypeDescriptor> Prototype, bool IsMasked,
104071fd6616SZakk Chen     bool HasMaskedOffOperand, bool HasVL, unsigned NF,
10410019226cSeopXD     PolicyScheme DefaultScheme, Policy PolicyAttrs, bool IsTuple) {
10421fa7f05bSKazu Hirata   SmallVector<PrototypeDescriptor> NewPrototype(Prototype);
1043dffdca85SZakk Chen   bool HasPassthruOp = DefaultScheme == PolicyScheme::HasPassthruOperand;
1044bc4eef50SZakk Chen   if (IsMasked) {
104571fd6616SZakk Chen     // If HasMaskedOffOperand, insert result type as first input operand if
104671fd6616SZakk Chen     // need.
10471deb6bceSeopXD     if (HasMaskedOffOperand && !PolicyAttrs.isTAMAPolicy()) {
1048010f3298SZakk Chen       if (NF == 1) {
1049bc4eef50SZakk Chen         NewPrototype.insert(NewPrototype.begin() + 1, NewPrototype[0]);
105071fd6616SZakk Chen       } else if (NF > 1) {
10510e9548bbSeopXD         if (IsTuple) {
10520e9548bbSeopXD           PrototypeDescriptor BasePtrOperand = Prototype[1];
10530e9548bbSeopXD           PrototypeDescriptor MaskoffType = PrototypeDescriptor(
10540e9548bbSeopXD               static_cast<uint8_t>(BaseTypeModifier::Vector),
10550e9548bbSeopXD               static_cast<uint8_t>(getTupleVTM(NF)),
10560e9548bbSeopXD               BasePtrOperand.TM & ~static_cast<uint8_t>(TypeModifier::Pointer));
10570e9548bbSeopXD           NewPrototype.insert(NewPrototype.begin() + 1, MaskoffType);
10580e9548bbSeopXD         } else {
1059bc4eef50SZakk Chen           // Convert
1060bc4eef50SZakk Chen           // (void, op0 address, op1 address, ...)
1061bc4eef50SZakk Chen           // to
1062bc4eef50SZakk Chen           // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
1063bc4eef50SZakk Chen           PrototypeDescriptor MaskoffType = NewPrototype[1];
1064bc4eef50SZakk Chen           MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer);
1065904a79f9SeopXD           NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1066bc4eef50SZakk Chen         }
1067bc4eef50SZakk Chen       }
10680e9548bbSeopXD     }
1069bc4eef50SZakk Chen     if (HasMaskedOffOperand && NF > 1) {
1070bc4eef50SZakk Chen       // Convert
1071bc4eef50SZakk Chen       // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
1072bc4eef50SZakk Chen       // to
1073bc4eef50SZakk Chen       // (void, op0 address, op1 address, ..., mask, maskedoff0, maskedoff1,
1074bc4eef50SZakk Chen       // ...)
10750019226cSeopXD       if (IsTuple)
10760019226cSeopXD         NewPrototype.insert(NewPrototype.begin() + 1,
10770019226cSeopXD                             PrototypeDescriptor::Mask);
10780019226cSeopXD       else
1079bc4eef50SZakk Chen         NewPrototype.insert(NewPrototype.begin() + NF + 1,
1080bc4eef50SZakk Chen                             PrototypeDescriptor::Mask);
1081bc4eef50SZakk Chen     } else {
1082bc4eef50SZakk Chen       // If IsMasked, insert PrototypeDescriptor:Mask as first input operand.
1083bc4eef50SZakk Chen       NewPrototype.insert(NewPrototype.begin() + 1, PrototypeDescriptor::Mask);
1084bc4eef50SZakk Chen     }
1085010f3298SZakk Chen   } else {
1086010f3298SZakk Chen     if (NF == 1) {
10876b282294SeopXD       if (PolicyAttrs.isTUPolicy() && HasPassthruOp)
108871fd6616SZakk Chen         NewPrototype.insert(NewPrototype.begin(), NewPrototype[0]);
10891deb6bceSeopXD     } else if (PolicyAttrs.isTUPolicy() && HasPassthruOp) {
10900e9548bbSeopXD       if (IsTuple) {
10910e9548bbSeopXD         PrototypeDescriptor BasePtrOperand = Prototype[0];
10920e9548bbSeopXD         PrototypeDescriptor MaskoffType = PrototypeDescriptor(
10930e9548bbSeopXD             static_cast<uint8_t>(BaseTypeModifier::Vector),
10940e9548bbSeopXD             static_cast<uint8_t>(getTupleVTM(NF)),
10950e9548bbSeopXD             BasePtrOperand.TM & ~static_cast<uint8_t>(TypeModifier::Pointer));
10960e9548bbSeopXD         NewPrototype.insert(NewPrototype.begin(), MaskoffType);
10970e9548bbSeopXD       } else {
1098010f3298SZakk Chen         // NF > 1 cases for segment load operations.
1099010f3298SZakk Chen         // Convert
1100010f3298SZakk Chen         // (void, op0 address, op1 address, ...)
1101010f3298SZakk Chen         // to
1102010f3298SZakk Chen         // (void, op0 address, op1 address, maskedoff0, maskedoff1, ...)
1103010f3298SZakk Chen         PrototypeDescriptor MaskoffType = Prototype[1];
1104010f3298SZakk Chen         MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer);
1105904a79f9SeopXD         NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1106010f3298SZakk Chen       }
1107bc4eef50SZakk Chen     }
11080e9548bbSeopXD  }
1109bc4eef50SZakk Chen 
1110bc4eef50SZakk Chen   // If HasVL, append PrototypeDescriptor:VL to last operand
1111bc4eef50SZakk Chen   if (HasVL)
1112bc4eef50SZakk Chen     NewPrototype.push_back(PrototypeDescriptor::VL);
11135847ec4dSeopXD 
1114bc4eef50SZakk Chen   return NewPrototype;
1115bc4eef50SZakk Chen }
1116bc4eef50SZakk Chen 
1117d94a315eSeopXD llvm::SmallVector<Policy> RVVIntrinsic::getSupportedUnMaskedPolicies() {
1118d94a315eSeopXD   return {Policy(Policy::PolicyType::Undisturbed)}; // TU
111962449823SeopXD }
112062449823SeopXD 
112171fd6616SZakk Chen llvm::SmallVector<Policy>
112271fd6616SZakk Chen RVVIntrinsic::getSupportedMaskedPolicies(bool HasTailPolicy,
112371fd6616SZakk Chen                                          bool HasMaskPolicy) {
112471fd6616SZakk Chen   if (HasTailPolicy && HasMaskPolicy)
1125d94a315eSeopXD     return {Policy(Policy::PolicyType::Undisturbed,
1126d94a315eSeopXD                    Policy::PolicyType::Agnostic), // TUM
1127d94a315eSeopXD             Policy(Policy::PolicyType::Undisturbed,
1128d94a315eSeopXD                    Policy::PolicyType::Undisturbed), // TUMU
1129d94a315eSeopXD             Policy(Policy::PolicyType::Agnostic,
1130d94a315eSeopXD                    Policy::PolicyType::Undisturbed)}; // MU
113106380284SeopXD   if (HasTailPolicy && !HasMaskPolicy)
11320d4c6506SPiyou Chen     return {Policy(Policy::PolicyType::Undisturbed,
1133d94a315eSeopXD                    Policy::PolicyType::Agnostic)}; // TU
113406380284SeopXD   if (!HasTailPolicy && HasMaskPolicy)
1135d94a315eSeopXD     return {Policy(Policy::PolicyType::Agnostic,
1136d94a315eSeopXD                    Policy::PolicyType::Undisturbed)}; // MU
113706380284SeopXD   llvm_unreachable("An RVV instruction should not be without both tail policy "
113806380284SeopXD                    "and mask policy");
113971fd6616SZakk Chen }
114071fd6616SZakk Chen 
114176482078SeopXD void RVVIntrinsic::updateNamesAndPolicy(
114276482078SeopXD     bool IsMasked, bool HasPolicy, std::string &Name, std::string &BuiltinName,
114376482078SeopXD     std::string &OverloadedName, Policy &PolicyAttrs, bool HasFRMRoundModeOp) {
114471fd6616SZakk Chen 
114571fd6616SZakk Chen   auto appendPolicySuffix = [&](const std::string &suffix) {
114671fd6616SZakk Chen     Name += suffix;
114771fd6616SZakk Chen     BuiltinName += suffix;
114871fd6616SZakk Chen     OverloadedName += suffix;
114971fd6616SZakk Chen   };
115071fd6616SZakk Chen 
115176482078SeopXD   if (HasFRMRoundModeOp) {
115276482078SeopXD     Name += "_rm";
115376482078SeopXD     BuiltinName += "_rm";
115476482078SeopXD   }
115576482078SeopXD 
115671fd6616SZakk Chen   if (IsMasked) {
1157d94a315eSeopXD     if (PolicyAttrs.isTUMUPolicy())
1158d94a315eSeopXD       appendPolicySuffix("_tumu");
1159d94a315eSeopXD     else if (PolicyAttrs.isTUMAPolicy())
1160d94a315eSeopXD       appendPolicySuffix("_tum");
1161d94a315eSeopXD     else if (PolicyAttrs.isTAMUPolicy())
1162d94a315eSeopXD       appendPolicySuffix("_mu");
1163d94a315eSeopXD     else if (PolicyAttrs.isTAMAPolicy()) {
116471fd6616SZakk Chen       Name += "_m";
116571fd6616SZakk Chen       BuiltinName += "_m";
1166d94a315eSeopXD     } else
1167377d2604SeopXD       llvm_unreachable("Unhandled policy condition");
1168377d2604SeopXD   } else {
1169377d2604SeopXD     if (PolicyAttrs.isTUPolicy())
11700d4c6506SPiyou Chen       appendPolicySuffix("_tu");
11715704630eSeopXD     else if (PolicyAttrs.isTAPolicy()) // no suffix needed
11725704630eSeopXD       return;
11735704630eSeopXD     else
11746f0d0be5SeopXD       llvm_unreachable("Unhandled policy condition");
117571fd6616SZakk Chen   }
117671fd6616SZakk Chen }
117771fd6616SZakk Chen 
11787ff0bf57SKito Cheng SmallVector<PrototypeDescriptor> parsePrototypes(StringRef Prototypes) {
11797ff0bf57SKito Cheng   SmallVector<PrototypeDescriptor> PrototypeDescriptors;
118074f38df1SBrandon Wu   const StringRef Primaries("evwqom0ztulf");
11817ff0bf57SKito Cheng   while (!Prototypes.empty()) {
11827ff0bf57SKito Cheng     size_t Idx = 0;
11837ff0bf57SKito Cheng     // Skip over complex prototype because it could contain primitive type
11847ff0bf57SKito Cheng     // character.
11857ff0bf57SKito Cheng     if (Prototypes[0] == '(')
11867ff0bf57SKito Cheng       Idx = Prototypes.find_first_of(')');
11877ff0bf57SKito Cheng     Idx = Prototypes.find_first_of(Primaries, Idx);
11887ff0bf57SKito Cheng     assert(Idx != StringRef::npos);
11897ff0bf57SKito Cheng     auto PD = PrototypeDescriptor::parsePrototypeDescriptor(
11907ff0bf57SKito Cheng         Prototypes.slice(0, Idx + 1));
11917ff0bf57SKito Cheng     if (!PD)
11927ff0bf57SKito Cheng       llvm_unreachable("Error during parsing prototype.");
11937ff0bf57SKito Cheng     PrototypeDescriptors.push_back(*PD);
11947ff0bf57SKito Cheng     Prototypes = Prototypes.drop_front(Idx + 1);
11957ff0bf57SKito Cheng   }
11967ff0bf57SKito Cheng   return PrototypeDescriptors;
11977ff0bf57SKito Cheng }
11987ff0bf57SKito Cheng 
11997a5cb15eSKito Cheng raw_ostream &operator<<(raw_ostream &OS, const RVVIntrinsicRecord &Record) {
12007a5cb15eSKito Cheng   OS << "{";
12017a5cb15eSKito Cheng   OS << "\"" << Record.Name << "\",";
12027a5cb15eSKito Cheng   if (Record.OverloadedName == nullptr ||
12037a5cb15eSKito Cheng       StringRef(Record.OverloadedName).empty())
12047a5cb15eSKito Cheng     OS << "nullptr,";
12057a5cb15eSKito Cheng   else
12067a5cb15eSKito Cheng     OS << "\"" << Record.OverloadedName << "\",";
12077a5cb15eSKito Cheng   OS << Record.PrototypeIndex << ",";
12087a5cb15eSKito Cheng   OS << Record.SuffixIndex << ",";
12097a5cb15eSKito Cheng   OS << Record.OverloadedSuffixIndex << ",";
12107a5cb15eSKito Cheng   OS << (int)Record.PrototypeLength << ",";
12117a5cb15eSKito Cheng   OS << (int)Record.SuffixLength << ",";
12127a5cb15eSKito Cheng   OS << (int)Record.OverloadedSuffixSize << ",";
121309058654SEric Biggers   OS << Record.RequiredExtensions << ",";
12147a5cb15eSKito Cheng   OS << (int)Record.TypeRangeMask << ",";
12157a5cb15eSKito Cheng   OS << (int)Record.Log2LMULMask << ",";
12167a5cb15eSKito Cheng   OS << (int)Record.NF << ",";
121793f8657cSZakk Chen   OS << (int)Record.HasMasked << ",";
121893f8657cSZakk Chen   OS << (int)Record.HasVL << ",";
121993f8657cSZakk Chen   OS << (int)Record.HasMaskedOffOperand << ",";
122071fd6616SZakk Chen   OS << (int)Record.HasTailPolicy << ",";
122171fd6616SZakk Chen   OS << (int)Record.HasMaskPolicy << ",";
122276482078SeopXD   OS << (int)Record.HasFRMRoundModeOp << ",";
12230019226cSeopXD   OS << (int)Record.IsTuple << ",";
122471fd6616SZakk Chen   OS << (int)Record.UnMaskedPolicyScheme << ",";
122571fd6616SZakk Chen   OS << (int)Record.MaskedPolicyScheme << ",";
12267a5cb15eSKito Cheng   OS << "},\n";
12277a5cb15eSKito Cheng   return OS;
12287a5cb15eSKito Cheng }
12297a5cb15eSKito Cheng 
1230f26c41e8SKito Cheng } // end namespace RISCV
1231f26c41e8SKito Cheng } // end namespace clang
1232