xref: /freebsd-src/contrib/llvm-project/clang/lib/Support/RISCVVIntrinsicUtils.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1*81ad6265SDimitry Andric //===- RISCVVIntrinsicUtils.cpp - RISC-V Vector Intrinsic Utils -*- C++ -*-===//
2*81ad6265SDimitry Andric //
3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*81ad6265SDimitry Andric //
7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===//
8*81ad6265SDimitry Andric 
9*81ad6265SDimitry Andric #include "clang/Support/RISCVVIntrinsicUtils.h"
10*81ad6265SDimitry Andric #include "llvm/ADT/ArrayRef.h"
11*81ad6265SDimitry Andric #include "llvm/ADT/Optional.h"
12*81ad6265SDimitry Andric #include "llvm/ADT/SmallSet.h"
13*81ad6265SDimitry Andric #include "llvm/ADT/StringExtras.h"
14*81ad6265SDimitry Andric #include "llvm/ADT/StringMap.h"
15*81ad6265SDimitry Andric #include "llvm/ADT/StringSet.h"
16*81ad6265SDimitry Andric #include "llvm/ADT/Twine.h"
17*81ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h"
18*81ad6265SDimitry Andric #include <numeric>
19*81ad6265SDimitry Andric #include <set>
20*81ad6265SDimitry Andric #include <unordered_map>
21*81ad6265SDimitry Andric 
22*81ad6265SDimitry Andric using namespace llvm;
23*81ad6265SDimitry Andric 
24*81ad6265SDimitry Andric namespace clang {
25*81ad6265SDimitry Andric namespace RISCV {
26*81ad6265SDimitry Andric 
27*81ad6265SDimitry Andric const PrototypeDescriptor PrototypeDescriptor::Mask = PrototypeDescriptor(
28*81ad6265SDimitry Andric     BaseTypeModifier::Vector, VectorTypeModifier::MaskVector);
29*81ad6265SDimitry Andric const PrototypeDescriptor PrototypeDescriptor::VL =
30*81ad6265SDimitry Andric     PrototypeDescriptor(BaseTypeModifier::SizeT);
31*81ad6265SDimitry Andric const PrototypeDescriptor PrototypeDescriptor::Vector =
32*81ad6265SDimitry Andric     PrototypeDescriptor(BaseTypeModifier::Vector);
33*81ad6265SDimitry Andric 
34*81ad6265SDimitry Andric //===----------------------------------------------------------------------===//
35*81ad6265SDimitry Andric // Type implementation
36*81ad6265SDimitry Andric //===----------------------------------------------------------------------===//
37*81ad6265SDimitry Andric 
38*81ad6265SDimitry Andric LMULType::LMULType(int NewLog2LMUL) {
39*81ad6265SDimitry Andric   // Check Log2LMUL is -3, -2, -1, 0, 1, 2, 3
40*81ad6265SDimitry Andric   assert(NewLog2LMUL <= 3 && NewLog2LMUL >= -3 && "Bad LMUL number!");
41*81ad6265SDimitry Andric   Log2LMUL = NewLog2LMUL;
42*81ad6265SDimitry Andric }
43*81ad6265SDimitry Andric 
44*81ad6265SDimitry Andric std::string LMULType::str() const {
45*81ad6265SDimitry Andric   if (Log2LMUL < 0)
46*81ad6265SDimitry Andric     return "mf" + utostr(1ULL << (-Log2LMUL));
47*81ad6265SDimitry Andric   return "m" + utostr(1ULL << Log2LMUL);
48*81ad6265SDimitry Andric }
49*81ad6265SDimitry Andric 
50*81ad6265SDimitry Andric VScaleVal LMULType::getScale(unsigned ElementBitwidth) const {
51*81ad6265SDimitry Andric   int Log2ScaleResult = 0;
52*81ad6265SDimitry Andric   switch (ElementBitwidth) {
53*81ad6265SDimitry Andric   default:
54*81ad6265SDimitry Andric     break;
55*81ad6265SDimitry Andric   case 8:
56*81ad6265SDimitry Andric     Log2ScaleResult = Log2LMUL + 3;
57*81ad6265SDimitry Andric     break;
58*81ad6265SDimitry Andric   case 16:
59*81ad6265SDimitry Andric     Log2ScaleResult = Log2LMUL + 2;
60*81ad6265SDimitry Andric     break;
61*81ad6265SDimitry Andric   case 32:
62*81ad6265SDimitry Andric     Log2ScaleResult = Log2LMUL + 1;
63*81ad6265SDimitry Andric     break;
64*81ad6265SDimitry Andric   case 64:
65*81ad6265SDimitry Andric     Log2ScaleResult = Log2LMUL;
66*81ad6265SDimitry Andric     break;
67*81ad6265SDimitry Andric   }
68*81ad6265SDimitry Andric   // Illegal vscale result would be less than 1
69*81ad6265SDimitry Andric   if (Log2ScaleResult < 0)
70*81ad6265SDimitry Andric     return llvm::None;
71*81ad6265SDimitry Andric   return 1 << Log2ScaleResult;
72*81ad6265SDimitry Andric }
73*81ad6265SDimitry Andric 
74*81ad6265SDimitry Andric void LMULType::MulLog2LMUL(int log2LMUL) { Log2LMUL += log2LMUL; }
75*81ad6265SDimitry Andric 
76*81ad6265SDimitry Andric RVVType::RVVType(BasicType BT, int Log2LMUL,
77*81ad6265SDimitry Andric                  const PrototypeDescriptor &prototype)
78*81ad6265SDimitry Andric     : BT(BT), LMUL(LMULType(Log2LMUL)) {
79*81ad6265SDimitry Andric   applyBasicType();
80*81ad6265SDimitry Andric   applyModifier(prototype);
81*81ad6265SDimitry Andric   Valid = verifyType();
82*81ad6265SDimitry Andric   if (Valid) {
83*81ad6265SDimitry Andric     initBuiltinStr();
84*81ad6265SDimitry Andric     initTypeStr();
85*81ad6265SDimitry Andric     if (isVector()) {
86*81ad6265SDimitry Andric       initClangBuiltinStr();
87*81ad6265SDimitry Andric     }
88*81ad6265SDimitry Andric   }
89*81ad6265SDimitry Andric }
90*81ad6265SDimitry Andric 
91*81ad6265SDimitry Andric // clang-format off
92*81ad6265SDimitry Andric // boolean type are encoded the ratio of n (SEW/LMUL)
93*81ad6265SDimitry Andric // SEW/LMUL | 1         | 2         | 4         | 8        | 16        | 32        | 64
94*81ad6265SDimitry Andric // c type   | vbool64_t | vbool32_t | vbool16_t | vbool8_t | vbool4_t  | vbool2_t  | vbool1_t
95*81ad6265SDimitry Andric // IR type  | nxv1i1    | nxv2i1    | nxv4i1    | nxv8i1   | nxv16i1   | nxv32i1   | nxv64i1
96*81ad6265SDimitry Andric 
97*81ad6265SDimitry Andric // type\lmul | 1/8    | 1/4      | 1/2     | 1       | 2        | 4        | 8
98*81ad6265SDimitry Andric // --------  |------  | -------- | ------- | ------- | -------- | -------- | --------
99*81ad6265SDimitry Andric // i64       | N/A    | N/A      | N/A     | nxv1i64 | nxv2i64  | nxv4i64  | nxv8i64
100*81ad6265SDimitry Andric // i32       | N/A    | N/A      | nxv1i32 | nxv2i32 | nxv4i32  | nxv8i32  | nxv16i32
101*81ad6265SDimitry Andric // i16       | N/A    | nxv1i16  | nxv2i16 | nxv4i16 | nxv8i16  | nxv16i16 | nxv32i16
102*81ad6265SDimitry Andric // i8        | nxv1i8 | nxv2i8   | nxv4i8  | nxv8i8  | nxv16i8  | nxv32i8  | nxv64i8
103*81ad6265SDimitry Andric // double    | N/A    | N/A      | N/A     | nxv1f64 | nxv2f64  | nxv4f64  | nxv8f64
104*81ad6265SDimitry Andric // float     | N/A    | N/A      | nxv1f32 | nxv2f32 | nxv4f32  | nxv8f32  | nxv16f32
105*81ad6265SDimitry Andric // half      | N/A    | nxv1f16  | nxv2f16 | nxv4f16 | nxv8f16  | nxv16f16 | nxv32f16
106*81ad6265SDimitry Andric // clang-format on
107*81ad6265SDimitry Andric 
108*81ad6265SDimitry Andric bool RVVType::verifyType() const {
109*81ad6265SDimitry Andric   if (ScalarType == Invalid)
110*81ad6265SDimitry Andric     return false;
111*81ad6265SDimitry Andric   if (isScalar())
112*81ad6265SDimitry Andric     return true;
113*81ad6265SDimitry Andric   if (!Scale)
114*81ad6265SDimitry Andric     return false;
115*81ad6265SDimitry Andric   if (isFloat() && ElementBitwidth == 8)
116*81ad6265SDimitry Andric     return false;
117*81ad6265SDimitry Andric   unsigned V = Scale.getValue();
118*81ad6265SDimitry Andric   switch (ElementBitwidth) {
119*81ad6265SDimitry Andric   case 1:
120*81ad6265SDimitry Andric   case 8:
121*81ad6265SDimitry Andric     // Check Scale is 1,2,4,8,16,32,64
122*81ad6265SDimitry Andric     return (V <= 64 && isPowerOf2_32(V));
123*81ad6265SDimitry Andric   case 16:
124*81ad6265SDimitry Andric     // Check Scale is 1,2,4,8,16,32
125*81ad6265SDimitry Andric     return (V <= 32 && isPowerOf2_32(V));
126*81ad6265SDimitry Andric   case 32:
127*81ad6265SDimitry Andric     // Check Scale is 1,2,4,8,16
128*81ad6265SDimitry Andric     return (V <= 16 && isPowerOf2_32(V));
129*81ad6265SDimitry Andric   case 64:
130*81ad6265SDimitry Andric     // Check Scale is 1,2,4,8
131*81ad6265SDimitry Andric     return (V <= 8 && isPowerOf2_32(V));
132*81ad6265SDimitry Andric   }
133*81ad6265SDimitry Andric   return false;
134*81ad6265SDimitry Andric }
135*81ad6265SDimitry Andric 
136*81ad6265SDimitry Andric void RVVType::initBuiltinStr() {
137*81ad6265SDimitry Andric   assert(isValid() && "RVVType is invalid");
138*81ad6265SDimitry Andric   switch (ScalarType) {
139*81ad6265SDimitry Andric   case ScalarTypeKind::Void:
140*81ad6265SDimitry Andric     BuiltinStr = "v";
141*81ad6265SDimitry Andric     return;
142*81ad6265SDimitry Andric   case ScalarTypeKind::Size_t:
143*81ad6265SDimitry Andric     BuiltinStr = "z";
144*81ad6265SDimitry Andric     if (IsImmediate)
145*81ad6265SDimitry Andric       BuiltinStr = "I" + BuiltinStr;
146*81ad6265SDimitry Andric     if (IsPointer)
147*81ad6265SDimitry Andric       BuiltinStr += "*";
148*81ad6265SDimitry Andric     return;
149*81ad6265SDimitry Andric   case ScalarTypeKind::Ptrdiff_t:
150*81ad6265SDimitry Andric     BuiltinStr = "Y";
151*81ad6265SDimitry Andric     return;
152*81ad6265SDimitry Andric   case ScalarTypeKind::UnsignedLong:
153*81ad6265SDimitry Andric     BuiltinStr = "ULi";
154*81ad6265SDimitry Andric     return;
155*81ad6265SDimitry Andric   case ScalarTypeKind::SignedLong:
156*81ad6265SDimitry Andric     BuiltinStr = "Li";
157*81ad6265SDimitry Andric     return;
158*81ad6265SDimitry Andric   case ScalarTypeKind::Boolean:
159*81ad6265SDimitry Andric     assert(ElementBitwidth == 1);
160*81ad6265SDimitry Andric     BuiltinStr += "b";
161*81ad6265SDimitry Andric     break;
162*81ad6265SDimitry Andric   case ScalarTypeKind::SignedInteger:
163*81ad6265SDimitry Andric   case ScalarTypeKind::UnsignedInteger:
164*81ad6265SDimitry Andric     switch (ElementBitwidth) {
165*81ad6265SDimitry Andric     case 8:
166*81ad6265SDimitry Andric       BuiltinStr += "c";
167*81ad6265SDimitry Andric       break;
168*81ad6265SDimitry Andric     case 16:
169*81ad6265SDimitry Andric       BuiltinStr += "s";
170*81ad6265SDimitry Andric       break;
171*81ad6265SDimitry Andric     case 32:
172*81ad6265SDimitry Andric       BuiltinStr += "i";
173*81ad6265SDimitry Andric       break;
174*81ad6265SDimitry Andric     case 64:
175*81ad6265SDimitry Andric       BuiltinStr += "Wi";
176*81ad6265SDimitry Andric       break;
177*81ad6265SDimitry Andric     default:
178*81ad6265SDimitry Andric       llvm_unreachable("Unhandled ElementBitwidth!");
179*81ad6265SDimitry Andric     }
180*81ad6265SDimitry Andric     if (isSignedInteger())
181*81ad6265SDimitry Andric       BuiltinStr = "S" + BuiltinStr;
182*81ad6265SDimitry Andric     else
183*81ad6265SDimitry Andric       BuiltinStr = "U" + BuiltinStr;
184*81ad6265SDimitry Andric     break;
185*81ad6265SDimitry Andric   case ScalarTypeKind::Float:
186*81ad6265SDimitry Andric     switch (ElementBitwidth) {
187*81ad6265SDimitry Andric     case 16:
188*81ad6265SDimitry Andric       BuiltinStr += "x";
189*81ad6265SDimitry Andric       break;
190*81ad6265SDimitry Andric     case 32:
191*81ad6265SDimitry Andric       BuiltinStr += "f";
192*81ad6265SDimitry Andric       break;
193*81ad6265SDimitry Andric     case 64:
194*81ad6265SDimitry Andric       BuiltinStr += "d";
195*81ad6265SDimitry Andric       break;
196*81ad6265SDimitry Andric     default:
197*81ad6265SDimitry Andric       llvm_unreachable("Unhandled ElementBitwidth!");
198*81ad6265SDimitry Andric     }
199*81ad6265SDimitry Andric     break;
200*81ad6265SDimitry Andric   default:
201*81ad6265SDimitry Andric     llvm_unreachable("ScalarType is invalid!");
202*81ad6265SDimitry Andric   }
203*81ad6265SDimitry Andric   if (IsImmediate)
204*81ad6265SDimitry Andric     BuiltinStr = "I" + BuiltinStr;
205*81ad6265SDimitry Andric   if (isScalar()) {
206*81ad6265SDimitry Andric     if (IsConstant)
207*81ad6265SDimitry Andric       BuiltinStr += "C";
208*81ad6265SDimitry Andric     if (IsPointer)
209*81ad6265SDimitry Andric       BuiltinStr += "*";
210*81ad6265SDimitry Andric     return;
211*81ad6265SDimitry Andric   }
212*81ad6265SDimitry Andric   BuiltinStr = "q" + utostr(*Scale) + BuiltinStr;
213*81ad6265SDimitry Andric   // Pointer to vector types. Defined for segment load intrinsics.
214*81ad6265SDimitry Andric   // segment load intrinsics have pointer type arguments to store the loaded
215*81ad6265SDimitry Andric   // vector values.
216*81ad6265SDimitry Andric   if (IsPointer)
217*81ad6265SDimitry Andric     BuiltinStr += "*";
218*81ad6265SDimitry Andric }
219*81ad6265SDimitry Andric 
220*81ad6265SDimitry Andric void RVVType::initClangBuiltinStr() {
221*81ad6265SDimitry Andric   assert(isValid() && "RVVType is invalid");
222*81ad6265SDimitry Andric   assert(isVector() && "Handle Vector type only");
223*81ad6265SDimitry Andric 
224*81ad6265SDimitry Andric   ClangBuiltinStr = "__rvv_";
225*81ad6265SDimitry Andric   switch (ScalarType) {
226*81ad6265SDimitry Andric   case ScalarTypeKind::Boolean:
227*81ad6265SDimitry Andric     ClangBuiltinStr += "bool" + utostr(64 / *Scale) + "_t";
228*81ad6265SDimitry Andric     return;
229*81ad6265SDimitry Andric   case ScalarTypeKind::Float:
230*81ad6265SDimitry Andric     ClangBuiltinStr += "float";
231*81ad6265SDimitry Andric     break;
232*81ad6265SDimitry Andric   case ScalarTypeKind::SignedInteger:
233*81ad6265SDimitry Andric     ClangBuiltinStr += "int";
234*81ad6265SDimitry Andric     break;
235*81ad6265SDimitry Andric   case ScalarTypeKind::UnsignedInteger:
236*81ad6265SDimitry Andric     ClangBuiltinStr += "uint";
237*81ad6265SDimitry Andric     break;
238*81ad6265SDimitry Andric   default:
239*81ad6265SDimitry Andric     llvm_unreachable("ScalarTypeKind is invalid");
240*81ad6265SDimitry Andric   }
241*81ad6265SDimitry Andric   ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.str() + "_t";
242*81ad6265SDimitry Andric }
243*81ad6265SDimitry Andric 
244*81ad6265SDimitry Andric void RVVType::initTypeStr() {
245*81ad6265SDimitry Andric   assert(isValid() && "RVVType is invalid");
246*81ad6265SDimitry Andric 
247*81ad6265SDimitry Andric   if (IsConstant)
248*81ad6265SDimitry Andric     Str += "const ";
249*81ad6265SDimitry Andric 
250*81ad6265SDimitry Andric   auto getTypeString = [&](StringRef TypeStr) {
251*81ad6265SDimitry Andric     if (isScalar())
252*81ad6265SDimitry Andric       return Twine(TypeStr + Twine(ElementBitwidth) + "_t").str();
253*81ad6265SDimitry Andric     return Twine("v" + TypeStr + Twine(ElementBitwidth) + LMUL.str() + "_t")
254*81ad6265SDimitry Andric         .str();
255*81ad6265SDimitry Andric   };
256*81ad6265SDimitry Andric 
257*81ad6265SDimitry Andric   switch (ScalarType) {
258*81ad6265SDimitry Andric   case ScalarTypeKind::Void:
259*81ad6265SDimitry Andric     Str = "void";
260*81ad6265SDimitry Andric     return;
261*81ad6265SDimitry Andric   case ScalarTypeKind::Size_t:
262*81ad6265SDimitry Andric     Str = "size_t";
263*81ad6265SDimitry Andric     if (IsPointer)
264*81ad6265SDimitry Andric       Str += " *";
265*81ad6265SDimitry Andric     return;
266*81ad6265SDimitry Andric   case ScalarTypeKind::Ptrdiff_t:
267*81ad6265SDimitry Andric     Str = "ptrdiff_t";
268*81ad6265SDimitry Andric     return;
269*81ad6265SDimitry Andric   case ScalarTypeKind::UnsignedLong:
270*81ad6265SDimitry Andric     Str = "unsigned long";
271*81ad6265SDimitry Andric     return;
272*81ad6265SDimitry Andric   case ScalarTypeKind::SignedLong:
273*81ad6265SDimitry Andric     Str = "long";
274*81ad6265SDimitry Andric     return;
275*81ad6265SDimitry Andric   case ScalarTypeKind::Boolean:
276*81ad6265SDimitry Andric     if (isScalar())
277*81ad6265SDimitry Andric       Str += "bool";
278*81ad6265SDimitry Andric     else
279*81ad6265SDimitry Andric       // Vector bool is special case, the formulate is
280*81ad6265SDimitry Andric       // `vbool<N>_t = MVT::nxv<64/N>i1` ex. vbool16_t = MVT::4i1
281*81ad6265SDimitry Andric       Str += "vbool" + utostr(64 / *Scale) + "_t";
282*81ad6265SDimitry Andric     break;
283*81ad6265SDimitry Andric   case ScalarTypeKind::Float:
284*81ad6265SDimitry Andric     if (isScalar()) {
285*81ad6265SDimitry Andric       if (ElementBitwidth == 64)
286*81ad6265SDimitry Andric         Str += "double";
287*81ad6265SDimitry Andric       else if (ElementBitwidth == 32)
288*81ad6265SDimitry Andric         Str += "float";
289*81ad6265SDimitry Andric       else if (ElementBitwidth == 16)
290*81ad6265SDimitry Andric         Str += "_Float16";
291*81ad6265SDimitry Andric       else
292*81ad6265SDimitry Andric         llvm_unreachable("Unhandled floating type.");
293*81ad6265SDimitry Andric     } else
294*81ad6265SDimitry Andric       Str += getTypeString("float");
295*81ad6265SDimitry Andric     break;
296*81ad6265SDimitry Andric   case ScalarTypeKind::SignedInteger:
297*81ad6265SDimitry Andric     Str += getTypeString("int");
298*81ad6265SDimitry Andric     break;
299*81ad6265SDimitry Andric   case ScalarTypeKind::UnsignedInteger:
300*81ad6265SDimitry Andric     Str += getTypeString("uint");
301*81ad6265SDimitry Andric     break;
302*81ad6265SDimitry Andric   default:
303*81ad6265SDimitry Andric     llvm_unreachable("ScalarType is invalid!");
304*81ad6265SDimitry Andric   }
305*81ad6265SDimitry Andric   if (IsPointer)
306*81ad6265SDimitry Andric     Str += " *";
307*81ad6265SDimitry Andric }
308*81ad6265SDimitry Andric 
309*81ad6265SDimitry Andric void RVVType::initShortStr() {
310*81ad6265SDimitry Andric   switch (ScalarType) {
311*81ad6265SDimitry Andric   case ScalarTypeKind::Boolean:
312*81ad6265SDimitry Andric     assert(isVector());
313*81ad6265SDimitry Andric     ShortStr = "b" + utostr(64 / *Scale);
314*81ad6265SDimitry Andric     return;
315*81ad6265SDimitry Andric   case ScalarTypeKind::Float:
316*81ad6265SDimitry Andric     ShortStr = "f" + utostr(ElementBitwidth);
317*81ad6265SDimitry Andric     break;
318*81ad6265SDimitry Andric   case ScalarTypeKind::SignedInteger:
319*81ad6265SDimitry Andric     ShortStr = "i" + utostr(ElementBitwidth);
320*81ad6265SDimitry Andric     break;
321*81ad6265SDimitry Andric   case ScalarTypeKind::UnsignedInteger:
322*81ad6265SDimitry Andric     ShortStr = "u" + utostr(ElementBitwidth);
323*81ad6265SDimitry Andric     break;
324*81ad6265SDimitry Andric   default:
325*81ad6265SDimitry Andric     llvm_unreachable("Unhandled case!");
326*81ad6265SDimitry Andric   }
327*81ad6265SDimitry Andric   if (isVector())
328*81ad6265SDimitry Andric     ShortStr += LMUL.str();
329*81ad6265SDimitry Andric }
330*81ad6265SDimitry Andric 
331*81ad6265SDimitry Andric void RVVType::applyBasicType() {
332*81ad6265SDimitry Andric   switch (BT) {
333*81ad6265SDimitry Andric   case BasicType::Int8:
334*81ad6265SDimitry Andric     ElementBitwidth = 8;
335*81ad6265SDimitry Andric     ScalarType = ScalarTypeKind::SignedInteger;
336*81ad6265SDimitry Andric     break;
337*81ad6265SDimitry Andric   case BasicType::Int16:
338*81ad6265SDimitry Andric     ElementBitwidth = 16;
339*81ad6265SDimitry Andric     ScalarType = ScalarTypeKind::SignedInteger;
340*81ad6265SDimitry Andric     break;
341*81ad6265SDimitry Andric   case BasicType::Int32:
342*81ad6265SDimitry Andric     ElementBitwidth = 32;
343*81ad6265SDimitry Andric     ScalarType = ScalarTypeKind::SignedInteger;
344*81ad6265SDimitry Andric     break;
345*81ad6265SDimitry Andric   case BasicType::Int64:
346*81ad6265SDimitry Andric     ElementBitwidth = 64;
347*81ad6265SDimitry Andric     ScalarType = ScalarTypeKind::SignedInteger;
348*81ad6265SDimitry Andric     break;
349*81ad6265SDimitry Andric   case BasicType::Float16:
350*81ad6265SDimitry Andric     ElementBitwidth = 16;
351*81ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Float;
352*81ad6265SDimitry Andric     break;
353*81ad6265SDimitry Andric   case BasicType::Float32:
354*81ad6265SDimitry Andric     ElementBitwidth = 32;
355*81ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Float;
356*81ad6265SDimitry Andric     break;
357*81ad6265SDimitry Andric   case BasicType::Float64:
358*81ad6265SDimitry Andric     ElementBitwidth = 64;
359*81ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Float;
360*81ad6265SDimitry Andric     break;
361*81ad6265SDimitry Andric   default:
362*81ad6265SDimitry Andric     llvm_unreachable("Unhandled type code!");
363*81ad6265SDimitry Andric   }
364*81ad6265SDimitry Andric   assert(ElementBitwidth != 0 && "Bad element bitwidth!");
365*81ad6265SDimitry Andric }
366*81ad6265SDimitry Andric 
367*81ad6265SDimitry Andric Optional<PrototypeDescriptor> PrototypeDescriptor::parsePrototypeDescriptor(
368*81ad6265SDimitry Andric     llvm::StringRef PrototypeDescriptorStr) {
369*81ad6265SDimitry Andric   PrototypeDescriptor PD;
370*81ad6265SDimitry Andric   BaseTypeModifier PT = BaseTypeModifier::Invalid;
371*81ad6265SDimitry Andric   VectorTypeModifier VTM = VectorTypeModifier::NoModifier;
372*81ad6265SDimitry Andric 
373*81ad6265SDimitry Andric   if (PrototypeDescriptorStr.empty())
374*81ad6265SDimitry Andric     return PD;
375*81ad6265SDimitry Andric 
376*81ad6265SDimitry Andric   // Handle base type modifier
377*81ad6265SDimitry Andric   auto PType = PrototypeDescriptorStr.back();
378*81ad6265SDimitry Andric   switch (PType) {
379*81ad6265SDimitry Andric   case 'e':
380*81ad6265SDimitry Andric     PT = BaseTypeModifier::Scalar;
381*81ad6265SDimitry Andric     break;
382*81ad6265SDimitry Andric   case 'v':
383*81ad6265SDimitry Andric     PT = BaseTypeModifier::Vector;
384*81ad6265SDimitry Andric     break;
385*81ad6265SDimitry Andric   case 'w':
386*81ad6265SDimitry Andric     PT = BaseTypeModifier::Vector;
387*81ad6265SDimitry Andric     VTM = VectorTypeModifier::Widening2XVector;
388*81ad6265SDimitry Andric     break;
389*81ad6265SDimitry Andric   case 'q':
390*81ad6265SDimitry Andric     PT = BaseTypeModifier::Vector;
391*81ad6265SDimitry Andric     VTM = VectorTypeModifier::Widening4XVector;
392*81ad6265SDimitry Andric     break;
393*81ad6265SDimitry Andric   case 'o':
394*81ad6265SDimitry Andric     PT = BaseTypeModifier::Vector;
395*81ad6265SDimitry Andric     VTM = VectorTypeModifier::Widening8XVector;
396*81ad6265SDimitry Andric     break;
397*81ad6265SDimitry Andric   case 'm':
398*81ad6265SDimitry Andric     PT = BaseTypeModifier::Vector;
399*81ad6265SDimitry Andric     VTM = VectorTypeModifier::MaskVector;
400*81ad6265SDimitry Andric     break;
401*81ad6265SDimitry Andric   case '0':
402*81ad6265SDimitry Andric     PT = BaseTypeModifier::Void;
403*81ad6265SDimitry Andric     break;
404*81ad6265SDimitry Andric   case 'z':
405*81ad6265SDimitry Andric     PT = BaseTypeModifier::SizeT;
406*81ad6265SDimitry Andric     break;
407*81ad6265SDimitry Andric   case 't':
408*81ad6265SDimitry Andric     PT = BaseTypeModifier::Ptrdiff;
409*81ad6265SDimitry Andric     break;
410*81ad6265SDimitry Andric   case 'u':
411*81ad6265SDimitry Andric     PT = BaseTypeModifier::UnsignedLong;
412*81ad6265SDimitry Andric     break;
413*81ad6265SDimitry Andric   case 'l':
414*81ad6265SDimitry Andric     PT = BaseTypeModifier::SignedLong;
415*81ad6265SDimitry Andric     break;
416*81ad6265SDimitry Andric   default:
417*81ad6265SDimitry Andric     llvm_unreachable("Illegal primitive type transformers!");
418*81ad6265SDimitry Andric   }
419*81ad6265SDimitry Andric   PD.PT = static_cast<uint8_t>(PT);
420*81ad6265SDimitry Andric   PrototypeDescriptorStr = PrototypeDescriptorStr.drop_back();
421*81ad6265SDimitry Andric 
422*81ad6265SDimitry Andric   // Compute the vector type transformers, it can only appear one time.
423*81ad6265SDimitry Andric   if (PrototypeDescriptorStr.startswith("(")) {
424*81ad6265SDimitry Andric     assert(VTM == VectorTypeModifier::NoModifier &&
425*81ad6265SDimitry Andric            "VectorTypeModifier should only have one modifier");
426*81ad6265SDimitry Andric     size_t Idx = PrototypeDescriptorStr.find(')');
427*81ad6265SDimitry Andric     assert(Idx != StringRef::npos);
428*81ad6265SDimitry Andric     StringRef ComplexType = PrototypeDescriptorStr.slice(1, Idx);
429*81ad6265SDimitry Andric     PrototypeDescriptorStr = PrototypeDescriptorStr.drop_front(Idx + 1);
430*81ad6265SDimitry Andric     assert(!PrototypeDescriptorStr.contains('(') &&
431*81ad6265SDimitry Andric            "Only allow one vector type modifier");
432*81ad6265SDimitry Andric 
433*81ad6265SDimitry Andric     auto ComplexTT = ComplexType.split(":");
434*81ad6265SDimitry Andric     if (ComplexTT.first == "Log2EEW") {
435*81ad6265SDimitry Andric       uint32_t Log2EEW;
436*81ad6265SDimitry Andric       if (ComplexTT.second.getAsInteger(10, Log2EEW)) {
437*81ad6265SDimitry Andric         llvm_unreachable("Invalid Log2EEW value!");
438*81ad6265SDimitry Andric         return None;
439*81ad6265SDimitry Andric       }
440*81ad6265SDimitry Andric       switch (Log2EEW) {
441*81ad6265SDimitry Andric       case 3:
442*81ad6265SDimitry Andric         VTM = VectorTypeModifier::Log2EEW3;
443*81ad6265SDimitry Andric         break;
444*81ad6265SDimitry Andric       case 4:
445*81ad6265SDimitry Andric         VTM = VectorTypeModifier::Log2EEW4;
446*81ad6265SDimitry Andric         break;
447*81ad6265SDimitry Andric       case 5:
448*81ad6265SDimitry Andric         VTM = VectorTypeModifier::Log2EEW5;
449*81ad6265SDimitry Andric         break;
450*81ad6265SDimitry Andric       case 6:
451*81ad6265SDimitry Andric         VTM = VectorTypeModifier::Log2EEW6;
452*81ad6265SDimitry Andric         break;
453*81ad6265SDimitry Andric       default:
454*81ad6265SDimitry Andric         llvm_unreachable("Invalid Log2EEW value, should be [3-6]");
455*81ad6265SDimitry Andric         return None;
456*81ad6265SDimitry Andric       }
457*81ad6265SDimitry Andric     } else if (ComplexTT.first == "FixedSEW") {
458*81ad6265SDimitry Andric       uint32_t NewSEW;
459*81ad6265SDimitry Andric       if (ComplexTT.second.getAsInteger(10, NewSEW)) {
460*81ad6265SDimitry Andric         llvm_unreachable("Invalid FixedSEW value!");
461*81ad6265SDimitry Andric         return None;
462*81ad6265SDimitry Andric       }
463*81ad6265SDimitry Andric       switch (NewSEW) {
464*81ad6265SDimitry Andric       case 8:
465*81ad6265SDimitry Andric         VTM = VectorTypeModifier::FixedSEW8;
466*81ad6265SDimitry Andric         break;
467*81ad6265SDimitry Andric       case 16:
468*81ad6265SDimitry Andric         VTM = VectorTypeModifier::FixedSEW16;
469*81ad6265SDimitry Andric         break;
470*81ad6265SDimitry Andric       case 32:
471*81ad6265SDimitry Andric         VTM = VectorTypeModifier::FixedSEW32;
472*81ad6265SDimitry Andric         break;
473*81ad6265SDimitry Andric       case 64:
474*81ad6265SDimitry Andric         VTM = VectorTypeModifier::FixedSEW64;
475*81ad6265SDimitry Andric         break;
476*81ad6265SDimitry Andric       default:
477*81ad6265SDimitry Andric         llvm_unreachable("Invalid FixedSEW value, should be 8, 16, 32 or 64");
478*81ad6265SDimitry Andric         return None;
479*81ad6265SDimitry Andric       }
480*81ad6265SDimitry Andric     } else if (ComplexTT.first == "LFixedLog2LMUL") {
481*81ad6265SDimitry Andric       int32_t Log2LMUL;
482*81ad6265SDimitry Andric       if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
483*81ad6265SDimitry Andric         llvm_unreachable("Invalid LFixedLog2LMUL value!");
484*81ad6265SDimitry Andric         return None;
485*81ad6265SDimitry Andric       }
486*81ad6265SDimitry Andric       switch (Log2LMUL) {
487*81ad6265SDimitry Andric       case -3:
488*81ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMULN3;
489*81ad6265SDimitry Andric         break;
490*81ad6265SDimitry Andric       case -2:
491*81ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMULN2;
492*81ad6265SDimitry Andric         break;
493*81ad6265SDimitry Andric       case -1:
494*81ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMULN1;
495*81ad6265SDimitry Andric         break;
496*81ad6265SDimitry Andric       case 0:
497*81ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMUL0;
498*81ad6265SDimitry Andric         break;
499*81ad6265SDimitry Andric       case 1:
500*81ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMUL1;
501*81ad6265SDimitry Andric         break;
502*81ad6265SDimitry Andric       case 2:
503*81ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMUL2;
504*81ad6265SDimitry Andric         break;
505*81ad6265SDimitry Andric       case 3:
506*81ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMUL3;
507*81ad6265SDimitry Andric         break;
508*81ad6265SDimitry Andric       default:
509*81ad6265SDimitry Andric         llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
510*81ad6265SDimitry Andric         return None;
511*81ad6265SDimitry Andric       }
512*81ad6265SDimitry Andric     } else if (ComplexTT.first == "SFixedLog2LMUL") {
513*81ad6265SDimitry Andric       int32_t Log2LMUL;
514*81ad6265SDimitry Andric       if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
515*81ad6265SDimitry Andric         llvm_unreachable("Invalid SFixedLog2LMUL value!");
516*81ad6265SDimitry Andric         return None;
517*81ad6265SDimitry Andric       }
518*81ad6265SDimitry Andric       switch (Log2LMUL) {
519*81ad6265SDimitry Andric       case -3:
520*81ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMULN3;
521*81ad6265SDimitry Andric         break;
522*81ad6265SDimitry Andric       case -2:
523*81ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMULN2;
524*81ad6265SDimitry Andric         break;
525*81ad6265SDimitry Andric       case -1:
526*81ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMULN1;
527*81ad6265SDimitry Andric         break;
528*81ad6265SDimitry Andric       case 0:
529*81ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMUL0;
530*81ad6265SDimitry Andric         break;
531*81ad6265SDimitry Andric       case 1:
532*81ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMUL1;
533*81ad6265SDimitry Andric         break;
534*81ad6265SDimitry Andric       case 2:
535*81ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMUL2;
536*81ad6265SDimitry Andric         break;
537*81ad6265SDimitry Andric       case 3:
538*81ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMUL3;
539*81ad6265SDimitry Andric         break;
540*81ad6265SDimitry Andric       default:
541*81ad6265SDimitry Andric         llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
542*81ad6265SDimitry Andric         return None;
543*81ad6265SDimitry Andric       }
544*81ad6265SDimitry Andric 
545*81ad6265SDimitry Andric     } else {
546*81ad6265SDimitry Andric       llvm_unreachable("Illegal complex type transformers!");
547*81ad6265SDimitry Andric     }
548*81ad6265SDimitry Andric   }
549*81ad6265SDimitry Andric   PD.VTM = static_cast<uint8_t>(VTM);
550*81ad6265SDimitry Andric 
551*81ad6265SDimitry Andric   // Compute the remain type transformers
552*81ad6265SDimitry Andric   TypeModifier TM = TypeModifier::NoModifier;
553*81ad6265SDimitry Andric   for (char I : PrototypeDescriptorStr) {
554*81ad6265SDimitry Andric     switch (I) {
555*81ad6265SDimitry Andric     case 'P':
556*81ad6265SDimitry Andric       if ((TM & TypeModifier::Const) == TypeModifier::Const)
557*81ad6265SDimitry Andric         llvm_unreachable("'P' transformer cannot be used after 'C'");
558*81ad6265SDimitry Andric       if ((TM & TypeModifier::Pointer) == TypeModifier::Pointer)
559*81ad6265SDimitry Andric         llvm_unreachable("'P' transformer cannot be used twice");
560*81ad6265SDimitry Andric       TM |= TypeModifier::Pointer;
561*81ad6265SDimitry Andric       break;
562*81ad6265SDimitry Andric     case 'C':
563*81ad6265SDimitry Andric       TM |= TypeModifier::Const;
564*81ad6265SDimitry Andric       break;
565*81ad6265SDimitry Andric     case 'K':
566*81ad6265SDimitry Andric       TM |= TypeModifier::Immediate;
567*81ad6265SDimitry Andric       break;
568*81ad6265SDimitry Andric     case 'U':
569*81ad6265SDimitry Andric       TM |= TypeModifier::UnsignedInteger;
570*81ad6265SDimitry Andric       break;
571*81ad6265SDimitry Andric     case 'I':
572*81ad6265SDimitry Andric       TM |= TypeModifier::SignedInteger;
573*81ad6265SDimitry Andric       break;
574*81ad6265SDimitry Andric     case 'F':
575*81ad6265SDimitry Andric       TM |= TypeModifier::Float;
576*81ad6265SDimitry Andric       break;
577*81ad6265SDimitry Andric     case 'S':
578*81ad6265SDimitry Andric       TM |= TypeModifier::LMUL1;
579*81ad6265SDimitry Andric       break;
580*81ad6265SDimitry Andric     default:
581*81ad6265SDimitry Andric       llvm_unreachable("Illegal non-primitive type transformer!");
582*81ad6265SDimitry Andric     }
583*81ad6265SDimitry Andric   }
584*81ad6265SDimitry Andric   PD.TM = static_cast<uint8_t>(TM);
585*81ad6265SDimitry Andric 
586*81ad6265SDimitry Andric   return PD;
587*81ad6265SDimitry Andric }
588*81ad6265SDimitry Andric 
589*81ad6265SDimitry Andric void RVVType::applyModifier(const PrototypeDescriptor &Transformer) {
590*81ad6265SDimitry Andric   // Handle primitive type transformer
591*81ad6265SDimitry Andric   switch (static_cast<BaseTypeModifier>(Transformer.PT)) {
592*81ad6265SDimitry Andric   case BaseTypeModifier::Scalar:
593*81ad6265SDimitry Andric     Scale = 0;
594*81ad6265SDimitry Andric     break;
595*81ad6265SDimitry Andric   case BaseTypeModifier::Vector:
596*81ad6265SDimitry Andric     Scale = LMUL.getScale(ElementBitwidth);
597*81ad6265SDimitry Andric     break;
598*81ad6265SDimitry Andric   case BaseTypeModifier::Void:
599*81ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Void;
600*81ad6265SDimitry Andric     break;
601*81ad6265SDimitry Andric   case BaseTypeModifier::SizeT:
602*81ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Size_t;
603*81ad6265SDimitry Andric     break;
604*81ad6265SDimitry Andric   case BaseTypeModifier::Ptrdiff:
605*81ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Ptrdiff_t;
606*81ad6265SDimitry Andric     break;
607*81ad6265SDimitry Andric   case BaseTypeModifier::UnsignedLong:
608*81ad6265SDimitry Andric     ScalarType = ScalarTypeKind::UnsignedLong;
609*81ad6265SDimitry Andric     break;
610*81ad6265SDimitry Andric   case BaseTypeModifier::SignedLong:
611*81ad6265SDimitry Andric     ScalarType = ScalarTypeKind::SignedLong;
612*81ad6265SDimitry Andric     break;
613*81ad6265SDimitry Andric   case BaseTypeModifier::Invalid:
614*81ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Invalid;
615*81ad6265SDimitry Andric     return;
616*81ad6265SDimitry Andric   }
617*81ad6265SDimitry Andric 
618*81ad6265SDimitry Andric   switch (static_cast<VectorTypeModifier>(Transformer.VTM)) {
619*81ad6265SDimitry Andric   case VectorTypeModifier::Widening2XVector:
620*81ad6265SDimitry Andric     ElementBitwidth *= 2;
621*81ad6265SDimitry Andric     LMUL.MulLog2LMUL(1);
622*81ad6265SDimitry Andric     Scale = LMUL.getScale(ElementBitwidth);
623*81ad6265SDimitry Andric     break;
624*81ad6265SDimitry Andric   case VectorTypeModifier::Widening4XVector:
625*81ad6265SDimitry Andric     ElementBitwidth *= 4;
626*81ad6265SDimitry Andric     LMUL.MulLog2LMUL(2);
627*81ad6265SDimitry Andric     Scale = LMUL.getScale(ElementBitwidth);
628*81ad6265SDimitry Andric     break;
629*81ad6265SDimitry Andric   case VectorTypeModifier::Widening8XVector:
630*81ad6265SDimitry Andric     ElementBitwidth *= 8;
631*81ad6265SDimitry Andric     LMUL.MulLog2LMUL(3);
632*81ad6265SDimitry Andric     Scale = LMUL.getScale(ElementBitwidth);
633*81ad6265SDimitry Andric     break;
634*81ad6265SDimitry Andric   case VectorTypeModifier::MaskVector:
635*81ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Boolean;
636*81ad6265SDimitry Andric     Scale = LMUL.getScale(ElementBitwidth);
637*81ad6265SDimitry Andric     ElementBitwidth = 1;
638*81ad6265SDimitry Andric     break;
639*81ad6265SDimitry Andric   case VectorTypeModifier::Log2EEW3:
640*81ad6265SDimitry Andric     applyLog2EEW(3);
641*81ad6265SDimitry Andric     break;
642*81ad6265SDimitry Andric   case VectorTypeModifier::Log2EEW4:
643*81ad6265SDimitry Andric     applyLog2EEW(4);
644*81ad6265SDimitry Andric     break;
645*81ad6265SDimitry Andric   case VectorTypeModifier::Log2EEW5:
646*81ad6265SDimitry Andric     applyLog2EEW(5);
647*81ad6265SDimitry Andric     break;
648*81ad6265SDimitry Andric   case VectorTypeModifier::Log2EEW6:
649*81ad6265SDimitry Andric     applyLog2EEW(6);
650*81ad6265SDimitry Andric     break;
651*81ad6265SDimitry Andric   case VectorTypeModifier::FixedSEW8:
652*81ad6265SDimitry Andric     applyFixedSEW(8);
653*81ad6265SDimitry Andric     break;
654*81ad6265SDimitry Andric   case VectorTypeModifier::FixedSEW16:
655*81ad6265SDimitry Andric     applyFixedSEW(16);
656*81ad6265SDimitry Andric     break;
657*81ad6265SDimitry Andric   case VectorTypeModifier::FixedSEW32:
658*81ad6265SDimitry Andric     applyFixedSEW(32);
659*81ad6265SDimitry Andric     break;
660*81ad6265SDimitry Andric   case VectorTypeModifier::FixedSEW64:
661*81ad6265SDimitry Andric     applyFixedSEW(64);
662*81ad6265SDimitry Andric     break;
663*81ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMULN3:
664*81ad6265SDimitry Andric     applyFixedLog2LMUL(-3, FixedLMULType::LargerThan);
665*81ad6265SDimitry Andric     break;
666*81ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMULN2:
667*81ad6265SDimitry Andric     applyFixedLog2LMUL(-2, FixedLMULType::LargerThan);
668*81ad6265SDimitry Andric     break;
669*81ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMULN1:
670*81ad6265SDimitry Andric     applyFixedLog2LMUL(-1, FixedLMULType::LargerThan);
671*81ad6265SDimitry Andric     break;
672*81ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMUL0:
673*81ad6265SDimitry Andric     applyFixedLog2LMUL(0, FixedLMULType::LargerThan);
674*81ad6265SDimitry Andric     break;
675*81ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMUL1:
676*81ad6265SDimitry Andric     applyFixedLog2LMUL(1, FixedLMULType::LargerThan);
677*81ad6265SDimitry Andric     break;
678*81ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMUL2:
679*81ad6265SDimitry Andric     applyFixedLog2LMUL(2, FixedLMULType::LargerThan);
680*81ad6265SDimitry Andric     break;
681*81ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMUL3:
682*81ad6265SDimitry Andric     applyFixedLog2LMUL(3, FixedLMULType::LargerThan);
683*81ad6265SDimitry Andric     break;
684*81ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMULN3:
685*81ad6265SDimitry Andric     applyFixedLog2LMUL(-3, FixedLMULType::SmallerThan);
686*81ad6265SDimitry Andric     break;
687*81ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMULN2:
688*81ad6265SDimitry Andric     applyFixedLog2LMUL(-2, FixedLMULType::SmallerThan);
689*81ad6265SDimitry Andric     break;
690*81ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMULN1:
691*81ad6265SDimitry Andric     applyFixedLog2LMUL(-1, FixedLMULType::SmallerThan);
692*81ad6265SDimitry Andric     break;
693*81ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMUL0:
694*81ad6265SDimitry Andric     applyFixedLog2LMUL(0, FixedLMULType::SmallerThan);
695*81ad6265SDimitry Andric     break;
696*81ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMUL1:
697*81ad6265SDimitry Andric     applyFixedLog2LMUL(1, FixedLMULType::SmallerThan);
698*81ad6265SDimitry Andric     break;
699*81ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMUL2:
700*81ad6265SDimitry Andric     applyFixedLog2LMUL(2, FixedLMULType::SmallerThan);
701*81ad6265SDimitry Andric     break;
702*81ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMUL3:
703*81ad6265SDimitry Andric     applyFixedLog2LMUL(3, FixedLMULType::SmallerThan);
704*81ad6265SDimitry Andric     break;
705*81ad6265SDimitry Andric   case VectorTypeModifier::NoModifier:
706*81ad6265SDimitry Andric     break;
707*81ad6265SDimitry Andric   }
708*81ad6265SDimitry Andric 
709*81ad6265SDimitry Andric   for (unsigned TypeModifierMaskShift = 0;
710*81ad6265SDimitry Andric        TypeModifierMaskShift <= static_cast<unsigned>(TypeModifier::MaxOffset);
711*81ad6265SDimitry Andric        ++TypeModifierMaskShift) {
712*81ad6265SDimitry Andric     unsigned TypeModifierMask = 1 << TypeModifierMaskShift;
713*81ad6265SDimitry Andric     if ((static_cast<unsigned>(Transformer.TM) & TypeModifierMask) !=
714*81ad6265SDimitry Andric         TypeModifierMask)
715*81ad6265SDimitry Andric       continue;
716*81ad6265SDimitry Andric     switch (static_cast<TypeModifier>(TypeModifierMask)) {
717*81ad6265SDimitry Andric     case TypeModifier::Pointer:
718*81ad6265SDimitry Andric       IsPointer = true;
719*81ad6265SDimitry Andric       break;
720*81ad6265SDimitry Andric     case TypeModifier::Const:
721*81ad6265SDimitry Andric       IsConstant = true;
722*81ad6265SDimitry Andric       break;
723*81ad6265SDimitry Andric     case TypeModifier::Immediate:
724*81ad6265SDimitry Andric       IsImmediate = true;
725*81ad6265SDimitry Andric       IsConstant = true;
726*81ad6265SDimitry Andric       break;
727*81ad6265SDimitry Andric     case TypeModifier::UnsignedInteger:
728*81ad6265SDimitry Andric       ScalarType = ScalarTypeKind::UnsignedInteger;
729*81ad6265SDimitry Andric       break;
730*81ad6265SDimitry Andric     case TypeModifier::SignedInteger:
731*81ad6265SDimitry Andric       ScalarType = ScalarTypeKind::SignedInteger;
732*81ad6265SDimitry Andric       break;
733*81ad6265SDimitry Andric     case TypeModifier::Float:
734*81ad6265SDimitry Andric       ScalarType = ScalarTypeKind::Float;
735*81ad6265SDimitry Andric       break;
736*81ad6265SDimitry Andric     case TypeModifier::LMUL1:
737*81ad6265SDimitry Andric       LMUL = LMULType(0);
738*81ad6265SDimitry Andric       // Update ElementBitwidth need to update Scale too.
739*81ad6265SDimitry Andric       Scale = LMUL.getScale(ElementBitwidth);
740*81ad6265SDimitry Andric       break;
741*81ad6265SDimitry Andric     default:
742*81ad6265SDimitry Andric       llvm_unreachable("Unknown type modifier mask!");
743*81ad6265SDimitry Andric     }
744*81ad6265SDimitry Andric   }
745*81ad6265SDimitry Andric }
746*81ad6265SDimitry Andric 
747*81ad6265SDimitry Andric void RVVType::applyLog2EEW(unsigned Log2EEW) {
748*81ad6265SDimitry Andric   // update new elmul = (eew/sew) * lmul
749*81ad6265SDimitry Andric   LMUL.MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth));
750*81ad6265SDimitry Andric   // update new eew
751*81ad6265SDimitry Andric   ElementBitwidth = 1 << Log2EEW;
752*81ad6265SDimitry Andric   ScalarType = ScalarTypeKind::SignedInteger;
753*81ad6265SDimitry Andric   Scale = LMUL.getScale(ElementBitwidth);
754*81ad6265SDimitry Andric }
755*81ad6265SDimitry Andric 
756*81ad6265SDimitry Andric void RVVType::applyFixedSEW(unsigned NewSEW) {
757*81ad6265SDimitry Andric   // Set invalid type if src and dst SEW are same.
758*81ad6265SDimitry Andric   if (ElementBitwidth == NewSEW) {
759*81ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Invalid;
760*81ad6265SDimitry Andric     return;
761*81ad6265SDimitry Andric   }
762*81ad6265SDimitry Andric   // Update new SEW
763*81ad6265SDimitry Andric   ElementBitwidth = NewSEW;
764*81ad6265SDimitry Andric   Scale = LMUL.getScale(ElementBitwidth);
765*81ad6265SDimitry Andric }
766*81ad6265SDimitry Andric 
767*81ad6265SDimitry Andric void RVVType::applyFixedLog2LMUL(int Log2LMUL, enum FixedLMULType Type) {
768*81ad6265SDimitry Andric   switch (Type) {
769*81ad6265SDimitry Andric   case FixedLMULType::LargerThan:
770*81ad6265SDimitry Andric     if (Log2LMUL < LMUL.Log2LMUL) {
771*81ad6265SDimitry Andric       ScalarType = ScalarTypeKind::Invalid;
772*81ad6265SDimitry Andric       return;
773*81ad6265SDimitry Andric     }
774*81ad6265SDimitry Andric     break;
775*81ad6265SDimitry Andric   case FixedLMULType::SmallerThan:
776*81ad6265SDimitry Andric     if (Log2LMUL > LMUL.Log2LMUL) {
777*81ad6265SDimitry Andric       ScalarType = ScalarTypeKind::Invalid;
778*81ad6265SDimitry Andric       return;
779*81ad6265SDimitry Andric     }
780*81ad6265SDimitry Andric     break;
781*81ad6265SDimitry Andric   }
782*81ad6265SDimitry Andric 
783*81ad6265SDimitry Andric   // Update new LMUL
784*81ad6265SDimitry Andric   LMUL = LMULType(Log2LMUL);
785*81ad6265SDimitry Andric   Scale = LMUL.getScale(ElementBitwidth);
786*81ad6265SDimitry Andric }
787*81ad6265SDimitry Andric 
788*81ad6265SDimitry Andric Optional<RVVTypes>
789*81ad6265SDimitry Andric RVVType::computeTypes(BasicType BT, int Log2LMUL, unsigned NF,
790*81ad6265SDimitry Andric                       ArrayRef<PrototypeDescriptor> Prototype) {
791*81ad6265SDimitry Andric   // LMUL x NF must be less than or equal to 8.
792*81ad6265SDimitry Andric   if ((Log2LMUL >= 1) && (1 << Log2LMUL) * NF > 8)
793*81ad6265SDimitry Andric     return llvm::None;
794*81ad6265SDimitry Andric 
795*81ad6265SDimitry Andric   RVVTypes Types;
796*81ad6265SDimitry Andric   for (const PrototypeDescriptor &Proto : Prototype) {
797*81ad6265SDimitry Andric     auto T = computeType(BT, Log2LMUL, Proto);
798*81ad6265SDimitry Andric     if (!T)
799*81ad6265SDimitry Andric       return llvm::None;
800*81ad6265SDimitry Andric     // Record legal type index
801*81ad6265SDimitry Andric     Types.push_back(T.getValue());
802*81ad6265SDimitry Andric   }
803*81ad6265SDimitry Andric   return Types;
804*81ad6265SDimitry Andric }
805*81ad6265SDimitry Andric 
806*81ad6265SDimitry Andric // Compute the hash value of RVVType, used for cache the result of computeType.
807*81ad6265SDimitry Andric static uint64_t computeRVVTypeHashValue(BasicType BT, int Log2LMUL,
808*81ad6265SDimitry Andric                                         PrototypeDescriptor Proto) {
809*81ad6265SDimitry Andric   // Layout of hash value:
810*81ad6265SDimitry Andric   // 0               8    16          24        32          40
811*81ad6265SDimitry Andric   // | Log2LMUL + 3  | BT  | Proto.PT | Proto.TM | Proto.VTM |
812*81ad6265SDimitry Andric   assert(Log2LMUL >= -3 && Log2LMUL <= 3);
813*81ad6265SDimitry Andric   return (Log2LMUL + 3) | (static_cast<uint64_t>(BT) & 0xff) << 8 |
814*81ad6265SDimitry Andric          ((uint64_t)(Proto.PT & 0xff) << 16) |
815*81ad6265SDimitry Andric          ((uint64_t)(Proto.TM & 0xff) << 24) |
816*81ad6265SDimitry Andric          ((uint64_t)(Proto.VTM & 0xff) << 32);
817*81ad6265SDimitry Andric }
818*81ad6265SDimitry Andric 
819*81ad6265SDimitry Andric Optional<RVVTypePtr> RVVType::computeType(BasicType BT, int Log2LMUL,
820*81ad6265SDimitry Andric                                           PrototypeDescriptor Proto) {
821*81ad6265SDimitry Andric   // Concat BasicType, LMUL and Proto as key
822*81ad6265SDimitry Andric   static std::unordered_map<uint64_t, RVVType> LegalTypes;
823*81ad6265SDimitry Andric   static std::set<uint64_t> IllegalTypes;
824*81ad6265SDimitry Andric   uint64_t Idx = computeRVVTypeHashValue(BT, Log2LMUL, Proto);
825*81ad6265SDimitry Andric   // Search first
826*81ad6265SDimitry Andric   auto It = LegalTypes.find(Idx);
827*81ad6265SDimitry Andric   if (It != LegalTypes.end())
828*81ad6265SDimitry Andric     return &(It->second);
829*81ad6265SDimitry Andric 
830*81ad6265SDimitry Andric   if (IllegalTypes.count(Idx))
831*81ad6265SDimitry Andric     return llvm::None;
832*81ad6265SDimitry Andric 
833*81ad6265SDimitry Andric   // Compute type and record the result.
834*81ad6265SDimitry Andric   RVVType T(BT, Log2LMUL, Proto);
835*81ad6265SDimitry Andric   if (T.isValid()) {
836*81ad6265SDimitry Andric     // Record legal type index and value.
837*81ad6265SDimitry Andric     LegalTypes.insert({Idx, T});
838*81ad6265SDimitry Andric     return &(LegalTypes[Idx]);
839*81ad6265SDimitry Andric   }
840*81ad6265SDimitry Andric   // Record illegal type index.
841*81ad6265SDimitry Andric   IllegalTypes.insert(Idx);
842*81ad6265SDimitry Andric   return llvm::None;
843*81ad6265SDimitry Andric }
844*81ad6265SDimitry Andric 
845*81ad6265SDimitry Andric //===----------------------------------------------------------------------===//
846*81ad6265SDimitry Andric // RVVIntrinsic implementation
847*81ad6265SDimitry Andric //===----------------------------------------------------------------------===//
848*81ad6265SDimitry Andric RVVIntrinsic::RVVIntrinsic(
849*81ad6265SDimitry Andric     StringRef NewName, StringRef Suffix, StringRef NewOverloadedName,
850*81ad6265SDimitry Andric     StringRef OverloadedSuffix, StringRef IRName, bool IsMasked,
851*81ad6265SDimitry Andric     bool HasMaskedOffOperand, bool HasVL, PolicyScheme Scheme,
852*81ad6265SDimitry Andric     bool HasUnMaskedOverloaded, bool HasBuiltinAlias, StringRef ManualCodegen,
853*81ad6265SDimitry Andric     const RVVTypes &OutInTypes, const std::vector<int64_t> &NewIntrinsicTypes,
854*81ad6265SDimitry Andric     const std::vector<StringRef> &RequiredFeatures, unsigned NF)
855*81ad6265SDimitry Andric     : IRName(IRName), IsMasked(IsMasked), HasVL(HasVL), Scheme(Scheme),
856*81ad6265SDimitry Andric       HasUnMaskedOverloaded(HasUnMaskedOverloaded),
857*81ad6265SDimitry Andric       HasBuiltinAlias(HasBuiltinAlias), ManualCodegen(ManualCodegen.str()),
858*81ad6265SDimitry Andric       NF(NF) {
859*81ad6265SDimitry Andric 
860*81ad6265SDimitry Andric   // Init BuiltinName, Name and OverloadedName
861*81ad6265SDimitry Andric   BuiltinName = NewName.str();
862*81ad6265SDimitry Andric   Name = BuiltinName;
863*81ad6265SDimitry Andric   if (NewOverloadedName.empty())
864*81ad6265SDimitry Andric     OverloadedName = NewName.split("_").first.str();
865*81ad6265SDimitry Andric   else
866*81ad6265SDimitry Andric     OverloadedName = NewOverloadedName.str();
867*81ad6265SDimitry Andric   if (!Suffix.empty())
868*81ad6265SDimitry Andric     Name += "_" + Suffix.str();
869*81ad6265SDimitry Andric   if (!OverloadedSuffix.empty())
870*81ad6265SDimitry Andric     OverloadedName += "_" + OverloadedSuffix.str();
871*81ad6265SDimitry Andric   if (IsMasked) {
872*81ad6265SDimitry Andric     BuiltinName += "_m";
873*81ad6265SDimitry Andric     Name += "_m";
874*81ad6265SDimitry Andric   }
875*81ad6265SDimitry Andric 
876*81ad6265SDimitry Andric   // Init RISC-V extensions
877*81ad6265SDimitry Andric   for (const auto &T : OutInTypes) {
878*81ad6265SDimitry Andric     if (T->isFloatVector(16) || T->isFloat(16))
879*81ad6265SDimitry Andric       RISCVPredefinedMacros |= RISCVPredefinedMacro::Zvfh;
880*81ad6265SDimitry Andric     if (T->isFloatVector(32))
881*81ad6265SDimitry Andric       RISCVPredefinedMacros |= RISCVPredefinedMacro::VectorMaxELenFp32;
882*81ad6265SDimitry Andric     if (T->isFloatVector(64))
883*81ad6265SDimitry Andric       RISCVPredefinedMacros |= RISCVPredefinedMacro::VectorMaxELenFp64;
884*81ad6265SDimitry Andric     if (T->isVector(64))
885*81ad6265SDimitry Andric       RISCVPredefinedMacros |= RISCVPredefinedMacro::VectorMaxELen64;
886*81ad6265SDimitry Andric   }
887*81ad6265SDimitry Andric   for (auto Feature : RequiredFeatures) {
888*81ad6265SDimitry Andric     if (Feature == "RV64")
889*81ad6265SDimitry Andric       RISCVPredefinedMacros |= RISCVPredefinedMacro::RV64;
890*81ad6265SDimitry Andric     // Note: Full multiply instruction (mulh, mulhu, mulhsu, smul) for EEW=64
891*81ad6265SDimitry Andric     // require V.
892*81ad6265SDimitry Andric     if (Feature == "FullMultiply" &&
893*81ad6265SDimitry Andric         (RISCVPredefinedMacros & RISCVPredefinedMacro::VectorMaxELen64))
894*81ad6265SDimitry Andric       RISCVPredefinedMacros |= RISCVPredefinedMacro::V;
895*81ad6265SDimitry Andric   }
896*81ad6265SDimitry Andric 
897*81ad6265SDimitry Andric   // Init OutputType and InputTypes
898*81ad6265SDimitry Andric   OutputType = OutInTypes[0];
899*81ad6265SDimitry Andric   InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
900*81ad6265SDimitry Andric 
901*81ad6265SDimitry Andric   // IntrinsicTypes is unmasked TA version index. Need to update it
902*81ad6265SDimitry Andric   // if there is merge operand (It is always in first operand).
903*81ad6265SDimitry Andric   IntrinsicTypes = NewIntrinsicTypes;
904*81ad6265SDimitry Andric   if ((IsMasked && HasMaskedOffOperand) ||
905*81ad6265SDimitry Andric       (!IsMasked && hasPassthruOperand())) {
906*81ad6265SDimitry Andric     for (auto &I : IntrinsicTypes) {
907*81ad6265SDimitry Andric       if (I >= 0)
908*81ad6265SDimitry Andric         I += NF;
909*81ad6265SDimitry Andric     }
910*81ad6265SDimitry Andric   }
911*81ad6265SDimitry Andric }
912*81ad6265SDimitry Andric 
913*81ad6265SDimitry Andric std::string RVVIntrinsic::getBuiltinTypeStr() const {
914*81ad6265SDimitry Andric   std::string S;
915*81ad6265SDimitry Andric   S += OutputType->getBuiltinStr();
916*81ad6265SDimitry Andric   for (const auto &T : InputTypes) {
917*81ad6265SDimitry Andric     S += T->getBuiltinStr();
918*81ad6265SDimitry Andric   }
919*81ad6265SDimitry Andric   return S;
920*81ad6265SDimitry Andric }
921*81ad6265SDimitry Andric 
922*81ad6265SDimitry Andric std::string RVVIntrinsic::getSuffixStr(
923*81ad6265SDimitry Andric     BasicType Type, int Log2LMUL,
924*81ad6265SDimitry Andric     llvm::ArrayRef<PrototypeDescriptor> PrototypeDescriptors) {
925*81ad6265SDimitry Andric   SmallVector<std::string> SuffixStrs;
926*81ad6265SDimitry Andric   for (auto PD : PrototypeDescriptors) {
927*81ad6265SDimitry Andric     auto T = RVVType::computeType(Type, Log2LMUL, PD);
928*81ad6265SDimitry Andric     SuffixStrs.push_back((*T)->getShortStr());
929*81ad6265SDimitry Andric   }
930*81ad6265SDimitry Andric   return join(SuffixStrs, "_");
931*81ad6265SDimitry Andric }
932*81ad6265SDimitry Andric 
933*81ad6265SDimitry Andric SmallVector<PrototypeDescriptor> parsePrototypes(StringRef Prototypes) {
934*81ad6265SDimitry Andric   SmallVector<PrototypeDescriptor> PrototypeDescriptors;
935*81ad6265SDimitry Andric   const StringRef Primaries("evwqom0ztul");
936*81ad6265SDimitry Andric   while (!Prototypes.empty()) {
937*81ad6265SDimitry Andric     size_t Idx = 0;
938*81ad6265SDimitry Andric     // Skip over complex prototype because it could contain primitive type
939*81ad6265SDimitry Andric     // character.
940*81ad6265SDimitry Andric     if (Prototypes[0] == '(')
941*81ad6265SDimitry Andric       Idx = Prototypes.find_first_of(')');
942*81ad6265SDimitry Andric     Idx = Prototypes.find_first_of(Primaries, Idx);
943*81ad6265SDimitry Andric     assert(Idx != StringRef::npos);
944*81ad6265SDimitry Andric     auto PD = PrototypeDescriptor::parsePrototypeDescriptor(
945*81ad6265SDimitry Andric         Prototypes.slice(0, Idx + 1));
946*81ad6265SDimitry Andric     if (!PD)
947*81ad6265SDimitry Andric       llvm_unreachable("Error during parsing prototype.");
948*81ad6265SDimitry Andric     PrototypeDescriptors.push_back(*PD);
949*81ad6265SDimitry Andric     Prototypes = Prototypes.drop_front(Idx + 1);
950*81ad6265SDimitry Andric   }
951*81ad6265SDimitry Andric   return PrototypeDescriptors;
952*81ad6265SDimitry Andric }
953*81ad6265SDimitry Andric 
954*81ad6265SDimitry Andric } // end namespace RISCV
955*81ad6265SDimitry Andric } // end namespace clang
956