xref: /freebsd/contrib/llvm-project/clang/lib/Support/RISCVVIntrinsicUtils.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===- RISCVVIntrinsicUtils.cpp - RISC-V Vector Intrinsic Utils -*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "clang/Support/RISCVVIntrinsicUtils.h"
10 #include "llvm/ADT/ArrayRef.h"
11 #include "llvm/ADT/SmallSet.h"
12 #include "llvm/ADT/StringExtras.h"
13 #include "llvm/ADT/StringSet.h"
14 #include "llvm/ADT/Twine.h"
15 #include "llvm/Support/ErrorHandling.h"
16 #include "llvm/Support/raw_ostream.h"
17 #include <numeric>
18 #include <optional>
19 
20 using namespace llvm;
21 
22 namespace clang {
23 namespace RISCV {
24 
25 const PrototypeDescriptor PrototypeDescriptor::Mask = PrototypeDescriptor(
26     BaseTypeModifier::Vector, VectorTypeModifier::MaskVector);
27 const PrototypeDescriptor PrototypeDescriptor::VL =
28     PrototypeDescriptor(BaseTypeModifier::SizeT);
29 const PrototypeDescriptor PrototypeDescriptor::Vector =
30     PrototypeDescriptor(BaseTypeModifier::Vector);
31 
32 //===----------------------------------------------------------------------===//
33 // Type implementation
34 //===----------------------------------------------------------------------===//
35 
LMULType(int NewLog2LMUL)36 LMULType::LMULType(int NewLog2LMUL) {
37   // Check Log2LMUL is -3, -2, -1, 0, 1, 2, 3
38   assert(NewLog2LMUL <= 3 && NewLog2LMUL >= -3 && "Bad LMUL number!");
39   Log2LMUL = NewLog2LMUL;
40 }
41 
str() const42 std::string LMULType::str() const {
43   if (Log2LMUL < 0)
44     return "mf" + utostr(1ULL << (-Log2LMUL));
45   return "m" + utostr(1ULL << Log2LMUL);
46 }
47 
getScale(unsigned ElementBitwidth) const48 VScaleVal LMULType::getScale(unsigned ElementBitwidth) const {
49   int Log2ScaleResult = 0;
50   switch (ElementBitwidth) {
51   default:
52     break;
53   case 8:
54     Log2ScaleResult = Log2LMUL + 3;
55     break;
56   case 16:
57     Log2ScaleResult = Log2LMUL + 2;
58     break;
59   case 32:
60     Log2ScaleResult = Log2LMUL + 1;
61     break;
62   case 64:
63     Log2ScaleResult = Log2LMUL;
64     break;
65   }
66   // Illegal vscale result would be less than 1
67   if (Log2ScaleResult < 0)
68     return std::nullopt;
69   return 1 << Log2ScaleResult;
70 }
71 
MulLog2LMUL(int log2LMUL)72 void LMULType::MulLog2LMUL(int log2LMUL) { Log2LMUL += log2LMUL; }
73 
RVVType(BasicType BT,int Log2LMUL,const PrototypeDescriptor & prototype)74 RVVType::RVVType(BasicType BT, int Log2LMUL,
75                  const PrototypeDescriptor &prototype)
76     : BT(BT), LMUL(LMULType(Log2LMUL)) {
77   applyBasicType();
78   applyModifier(prototype);
79   Valid = verifyType();
80   if (Valid) {
81     initBuiltinStr();
82     initTypeStr();
83     if (isVector()) {
84       initClangBuiltinStr();
85     }
86   }
87 }
88 
89 // clang-format off
90 // boolean type are encoded the ratio of n (SEW/LMUL)
91 // SEW/LMUL | 1         | 2         | 4         | 8        | 16        | 32        | 64
92 // c type   | vbool64_t | vbool32_t | vbool16_t | vbool8_t | vbool4_t  | vbool2_t  | vbool1_t
93 // IR type  | nxv1i1    | nxv2i1    | nxv4i1    | nxv8i1   | nxv16i1   | nxv32i1   | nxv64i1
94 
95 // type\lmul | 1/8    | 1/4      | 1/2     | 1       | 2        | 4        | 8
96 // --------  |------  | -------- | ------- | ------- | -------- | -------- | --------
97 // i64       | N/A    | N/A      | N/A     | nxv1i64 | nxv2i64  | nxv4i64  | nxv8i64
98 // i32       | N/A    | N/A      | nxv1i32 | nxv2i32 | nxv4i32  | nxv8i32  | nxv16i32
99 // i16       | N/A    | nxv1i16  | nxv2i16 | nxv4i16 | nxv8i16  | nxv16i16 | nxv32i16
100 // i8        | nxv1i8 | nxv2i8   | nxv4i8  | nxv8i8  | nxv16i8  | nxv32i8  | nxv64i8
101 // double    | N/A    | N/A      | N/A     | nxv1f64 | nxv2f64  | nxv4f64  | nxv8f64
102 // float     | N/A    | N/A      | nxv1f32 | nxv2f32 | nxv4f32  | nxv8f32  | nxv16f32
103 // half      | N/A    | nxv1f16  | nxv2f16 | nxv4f16 | nxv8f16  | nxv16f16 | nxv32f16
104 // bfloat16  | N/A    | nxv1bf16 | nxv2bf16| nxv4bf16| nxv8bf16 | nxv16bf16| nxv32bf16
105 // clang-format on
106 
verifyType() const107 bool RVVType::verifyType() const {
108   if (ScalarType == Invalid)
109     return false;
110   if (isScalar())
111     return true;
112   if (!Scale)
113     return false;
114   if (isFloat() && ElementBitwidth == 8)
115     return false;
116   if (isBFloat() && ElementBitwidth != 16)
117     return false;
118   if (IsTuple && (NF == 1 || NF > 8))
119     return false;
120   if (IsTuple && (1 << std::max(0, LMUL.Log2LMUL)) * NF > 8)
121     return false;
122   unsigned V = *Scale;
123   switch (ElementBitwidth) {
124   case 1:
125   case 8:
126     // Check Scale is 1,2,4,8,16,32,64
127     return (V <= 64 && isPowerOf2_32(V));
128   case 16:
129     // Check Scale is 1,2,4,8,16,32
130     return (V <= 32 && isPowerOf2_32(V));
131   case 32:
132     // Check Scale is 1,2,4,8,16
133     return (V <= 16 && isPowerOf2_32(V));
134   case 64:
135     // Check Scale is 1,2,4,8
136     return (V <= 8 && isPowerOf2_32(V));
137   }
138   return false;
139 }
140 
initBuiltinStr()141 void RVVType::initBuiltinStr() {
142   assert(isValid() && "RVVType is invalid");
143   switch (ScalarType) {
144   case ScalarTypeKind::Void:
145     BuiltinStr = "v";
146     return;
147   case ScalarTypeKind::Size_t:
148     BuiltinStr = "z";
149     if (IsImmediate)
150       BuiltinStr = "I" + BuiltinStr;
151     if (IsPointer)
152       BuiltinStr += "*";
153     return;
154   case ScalarTypeKind::Ptrdiff_t:
155     BuiltinStr = "Y";
156     return;
157   case ScalarTypeKind::UnsignedLong:
158     BuiltinStr = "ULi";
159     return;
160   case ScalarTypeKind::SignedLong:
161     BuiltinStr = "Li";
162     return;
163   case ScalarTypeKind::Boolean:
164     assert(ElementBitwidth == 1);
165     BuiltinStr += "b";
166     break;
167   case ScalarTypeKind::SignedInteger:
168   case ScalarTypeKind::UnsignedInteger:
169     switch (ElementBitwidth) {
170     case 8:
171       BuiltinStr += "c";
172       break;
173     case 16:
174       BuiltinStr += "s";
175       break;
176     case 32:
177       BuiltinStr += "i";
178       break;
179     case 64:
180       BuiltinStr += "Wi";
181       break;
182     default:
183       llvm_unreachable("Unhandled ElementBitwidth!");
184     }
185     if (isSignedInteger())
186       BuiltinStr = "S" + BuiltinStr;
187     else
188       BuiltinStr = "U" + BuiltinStr;
189     break;
190   case ScalarTypeKind::Float:
191     switch (ElementBitwidth) {
192     case 16:
193       BuiltinStr += "x";
194       break;
195     case 32:
196       BuiltinStr += "f";
197       break;
198     case 64:
199       BuiltinStr += "d";
200       break;
201     default:
202       llvm_unreachable("Unhandled ElementBitwidth!");
203     }
204     break;
205   case ScalarTypeKind::BFloat:
206     BuiltinStr += "y";
207     break;
208   default:
209     llvm_unreachable("ScalarType is invalid!");
210   }
211   if (IsImmediate)
212     BuiltinStr = "I" + BuiltinStr;
213   if (isScalar()) {
214     if (IsConstant)
215       BuiltinStr += "C";
216     if (IsPointer)
217       BuiltinStr += "*";
218     return;
219   }
220   BuiltinStr = "q" + utostr(*Scale) + BuiltinStr;
221   // Pointer to vector types. Defined for segment load intrinsics.
222   // segment load intrinsics have pointer type arguments to store the loaded
223   // vector values.
224   if (IsPointer)
225     BuiltinStr += "*";
226 
227   if (IsTuple)
228     BuiltinStr = "T" + utostr(NF) + BuiltinStr;
229 }
230 
initClangBuiltinStr()231 void RVVType::initClangBuiltinStr() {
232   assert(isValid() && "RVVType is invalid");
233   assert(isVector() && "Handle Vector type only");
234 
235   ClangBuiltinStr = "__rvv_";
236   switch (ScalarType) {
237   case ScalarTypeKind::Boolean:
238     ClangBuiltinStr += "bool" + utostr(64 / *Scale) + "_t";
239     return;
240   case ScalarTypeKind::Float:
241     ClangBuiltinStr += "float";
242     break;
243   case ScalarTypeKind::BFloat:
244     ClangBuiltinStr += "bfloat";
245     break;
246   case ScalarTypeKind::SignedInteger:
247     ClangBuiltinStr += "int";
248     break;
249   case ScalarTypeKind::UnsignedInteger:
250     ClangBuiltinStr += "uint";
251     break;
252   default:
253     llvm_unreachable("ScalarTypeKind is invalid");
254   }
255   ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.str() +
256                      (IsTuple ? "x" + utostr(NF) : "") + "_t";
257 }
258 
initTypeStr()259 void RVVType::initTypeStr() {
260   assert(isValid() && "RVVType is invalid");
261 
262   if (IsConstant)
263     Str += "const ";
264 
265   auto getTypeString = [&](StringRef TypeStr) {
266     if (isScalar())
267       return Twine(TypeStr + Twine(ElementBitwidth) + "_t").str();
268     return Twine("v" + TypeStr + Twine(ElementBitwidth) + LMUL.str() +
269                  (IsTuple ? "x" + utostr(NF) : "") + "_t")
270         .str();
271   };
272 
273   switch (ScalarType) {
274   case ScalarTypeKind::Void:
275     Str = "void";
276     return;
277   case ScalarTypeKind::Size_t:
278     Str = "size_t";
279     if (IsPointer)
280       Str += " *";
281     return;
282   case ScalarTypeKind::Ptrdiff_t:
283     Str = "ptrdiff_t";
284     return;
285   case ScalarTypeKind::UnsignedLong:
286     Str = "unsigned long";
287     return;
288   case ScalarTypeKind::SignedLong:
289     Str = "long";
290     return;
291   case ScalarTypeKind::Boolean:
292     if (isScalar())
293       Str += "bool";
294     else
295       // Vector bool is special case, the formulate is
296       // `vbool<N>_t = MVT::nxv<64/N>i1` ex. vbool16_t = MVT::4i1
297       Str += "vbool" + utostr(64 / *Scale) + "_t";
298     break;
299   case ScalarTypeKind::Float:
300     if (isScalar()) {
301       if (ElementBitwidth == 64)
302         Str += "double";
303       else if (ElementBitwidth == 32)
304         Str += "float";
305       else if (ElementBitwidth == 16)
306         Str += "_Float16";
307       else
308         llvm_unreachable("Unhandled floating type.");
309     } else
310       Str += getTypeString("float");
311     break;
312   case ScalarTypeKind::BFloat:
313     if (isScalar()) {
314       if (ElementBitwidth == 16)
315         Str += "__bf16";
316       else
317         llvm_unreachable("Unhandled floating type.");
318     } else
319       Str += getTypeString("bfloat");
320     break;
321   case ScalarTypeKind::SignedInteger:
322     Str += getTypeString("int");
323     break;
324   case ScalarTypeKind::UnsignedInteger:
325     Str += getTypeString("uint");
326     break;
327   default:
328     llvm_unreachable("ScalarType is invalid!");
329   }
330   if (IsPointer)
331     Str += " *";
332 }
333 
initShortStr()334 void RVVType::initShortStr() {
335   switch (ScalarType) {
336   case ScalarTypeKind::Boolean:
337     assert(isVector());
338     ShortStr = "b" + utostr(64 / *Scale);
339     return;
340   case ScalarTypeKind::Float:
341     ShortStr = "f" + utostr(ElementBitwidth);
342     break;
343   case ScalarTypeKind::BFloat:
344     ShortStr = "bf" + utostr(ElementBitwidth);
345     break;
346   case ScalarTypeKind::SignedInteger:
347     ShortStr = "i" + utostr(ElementBitwidth);
348     break;
349   case ScalarTypeKind::UnsignedInteger:
350     ShortStr = "u" + utostr(ElementBitwidth);
351     break;
352   default:
353     llvm_unreachable("Unhandled case!");
354   }
355   if (isVector())
356     ShortStr += LMUL.str();
357   if (isTuple())
358     ShortStr += "x" + utostr(NF);
359 }
360 
getTupleVTM(unsigned NF)361 static VectorTypeModifier getTupleVTM(unsigned NF) {
362   assert(2 <= NF && NF <= 8 && "2 <= NF <= 8");
363   return static_cast<VectorTypeModifier>(
364       static_cast<uint8_t>(VectorTypeModifier::Tuple2) + (NF - 2));
365 }
366 
applyBasicType()367 void RVVType::applyBasicType() {
368   switch (BT) {
369   case BasicType::Int8:
370     ElementBitwidth = 8;
371     ScalarType = ScalarTypeKind::SignedInteger;
372     break;
373   case BasicType::Int16:
374     ElementBitwidth = 16;
375     ScalarType = ScalarTypeKind::SignedInteger;
376     break;
377   case BasicType::Int32:
378     ElementBitwidth = 32;
379     ScalarType = ScalarTypeKind::SignedInteger;
380     break;
381   case BasicType::Int64:
382     ElementBitwidth = 64;
383     ScalarType = ScalarTypeKind::SignedInteger;
384     break;
385   case BasicType::Float16:
386     ElementBitwidth = 16;
387     ScalarType = ScalarTypeKind::Float;
388     break;
389   case BasicType::Float32:
390     ElementBitwidth = 32;
391     ScalarType = ScalarTypeKind::Float;
392     break;
393   case BasicType::Float64:
394     ElementBitwidth = 64;
395     ScalarType = ScalarTypeKind::Float;
396     break;
397   case BasicType::BFloat16:
398     ElementBitwidth = 16;
399     ScalarType = ScalarTypeKind::BFloat;
400     break;
401   default:
402     llvm_unreachable("Unhandled type code!");
403   }
404   assert(ElementBitwidth != 0 && "Bad element bitwidth!");
405 }
406 
407 std::optional<PrototypeDescriptor>
parsePrototypeDescriptor(llvm::StringRef PrototypeDescriptorStr)408 PrototypeDescriptor::parsePrototypeDescriptor(
409     llvm::StringRef PrototypeDescriptorStr) {
410   PrototypeDescriptor PD;
411   BaseTypeModifier PT = BaseTypeModifier::Invalid;
412   VectorTypeModifier VTM = VectorTypeModifier::NoModifier;
413 
414   if (PrototypeDescriptorStr.empty())
415     return PD;
416 
417   // Handle base type modifier
418   auto PType = PrototypeDescriptorStr.back();
419   switch (PType) {
420   case 'e':
421     PT = BaseTypeModifier::Scalar;
422     break;
423   case 'v':
424     PT = BaseTypeModifier::Vector;
425     break;
426   case 'w':
427     PT = BaseTypeModifier::Vector;
428     VTM = VectorTypeModifier::Widening2XVector;
429     break;
430   case 'q':
431     PT = BaseTypeModifier::Vector;
432     VTM = VectorTypeModifier::Widening4XVector;
433     break;
434   case 'o':
435     PT = BaseTypeModifier::Vector;
436     VTM = VectorTypeModifier::Widening8XVector;
437     break;
438   case 'm':
439     PT = BaseTypeModifier::Vector;
440     VTM = VectorTypeModifier::MaskVector;
441     break;
442   case '0':
443     PT = BaseTypeModifier::Void;
444     break;
445   case 'z':
446     PT = BaseTypeModifier::SizeT;
447     break;
448   case 't':
449     PT = BaseTypeModifier::Ptrdiff;
450     break;
451   case 'u':
452     PT = BaseTypeModifier::UnsignedLong;
453     break;
454   case 'l':
455     PT = BaseTypeModifier::SignedLong;
456     break;
457   case 'f':
458     PT = BaseTypeModifier::Float32;
459     break;
460   default:
461     llvm_unreachable("Illegal primitive type transformers!");
462   }
463   PD.PT = static_cast<uint8_t>(PT);
464   PrototypeDescriptorStr = PrototypeDescriptorStr.drop_back();
465 
466   // Compute the vector type transformers, it can only appear one time.
467   if (PrototypeDescriptorStr.starts_with("(")) {
468     assert(VTM == VectorTypeModifier::NoModifier &&
469            "VectorTypeModifier should only have one modifier");
470     size_t Idx = PrototypeDescriptorStr.find(')');
471     assert(Idx != StringRef::npos);
472     StringRef ComplexType = PrototypeDescriptorStr.slice(1, Idx);
473     PrototypeDescriptorStr = PrototypeDescriptorStr.drop_front(Idx + 1);
474     assert(!PrototypeDescriptorStr.contains('(') &&
475            "Only allow one vector type modifier");
476 
477     auto ComplexTT = ComplexType.split(":");
478     if (ComplexTT.first == "Log2EEW") {
479       uint32_t Log2EEW;
480       if (ComplexTT.second.getAsInteger(10, Log2EEW)) {
481         llvm_unreachable("Invalid Log2EEW value!");
482         return std::nullopt;
483       }
484       switch (Log2EEW) {
485       case 3:
486         VTM = VectorTypeModifier::Log2EEW3;
487         break;
488       case 4:
489         VTM = VectorTypeModifier::Log2EEW4;
490         break;
491       case 5:
492         VTM = VectorTypeModifier::Log2EEW5;
493         break;
494       case 6:
495         VTM = VectorTypeModifier::Log2EEW6;
496         break;
497       default:
498         llvm_unreachable("Invalid Log2EEW value, should be [3-6]");
499         return std::nullopt;
500       }
501     } else if (ComplexTT.first == "FixedSEW") {
502       uint32_t NewSEW;
503       if (ComplexTT.second.getAsInteger(10, NewSEW)) {
504         llvm_unreachable("Invalid FixedSEW value!");
505         return std::nullopt;
506       }
507       switch (NewSEW) {
508       case 8:
509         VTM = VectorTypeModifier::FixedSEW8;
510         break;
511       case 16:
512         VTM = VectorTypeModifier::FixedSEW16;
513         break;
514       case 32:
515         VTM = VectorTypeModifier::FixedSEW32;
516         break;
517       case 64:
518         VTM = VectorTypeModifier::FixedSEW64;
519         break;
520       default:
521         llvm_unreachable("Invalid FixedSEW value, should be 8, 16, 32 or 64");
522         return std::nullopt;
523       }
524     } else if (ComplexTT.first == "LFixedLog2LMUL") {
525       int32_t Log2LMUL;
526       if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
527         llvm_unreachable("Invalid LFixedLog2LMUL value!");
528         return std::nullopt;
529       }
530       switch (Log2LMUL) {
531       case -3:
532         VTM = VectorTypeModifier::LFixedLog2LMULN3;
533         break;
534       case -2:
535         VTM = VectorTypeModifier::LFixedLog2LMULN2;
536         break;
537       case -1:
538         VTM = VectorTypeModifier::LFixedLog2LMULN1;
539         break;
540       case 0:
541         VTM = VectorTypeModifier::LFixedLog2LMUL0;
542         break;
543       case 1:
544         VTM = VectorTypeModifier::LFixedLog2LMUL1;
545         break;
546       case 2:
547         VTM = VectorTypeModifier::LFixedLog2LMUL2;
548         break;
549       case 3:
550         VTM = VectorTypeModifier::LFixedLog2LMUL3;
551         break;
552       default:
553         llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
554         return std::nullopt;
555       }
556     } else if (ComplexTT.first == "SFixedLog2LMUL") {
557       int32_t Log2LMUL;
558       if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
559         llvm_unreachable("Invalid SFixedLog2LMUL value!");
560         return std::nullopt;
561       }
562       switch (Log2LMUL) {
563       case -3:
564         VTM = VectorTypeModifier::SFixedLog2LMULN3;
565         break;
566       case -2:
567         VTM = VectorTypeModifier::SFixedLog2LMULN2;
568         break;
569       case -1:
570         VTM = VectorTypeModifier::SFixedLog2LMULN1;
571         break;
572       case 0:
573         VTM = VectorTypeModifier::SFixedLog2LMUL0;
574         break;
575       case 1:
576         VTM = VectorTypeModifier::SFixedLog2LMUL1;
577         break;
578       case 2:
579         VTM = VectorTypeModifier::SFixedLog2LMUL2;
580         break;
581       case 3:
582         VTM = VectorTypeModifier::SFixedLog2LMUL3;
583         break;
584       default:
585         llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
586         return std::nullopt;
587       }
588 
589     } else if (ComplexTT.first == "SEFixedLog2LMUL") {
590       int32_t Log2LMUL;
591       if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
592         llvm_unreachable("Invalid SEFixedLog2LMUL value!");
593         return std::nullopt;
594       }
595       switch (Log2LMUL) {
596       case -3:
597         VTM = VectorTypeModifier::SEFixedLog2LMULN3;
598         break;
599       case -2:
600         VTM = VectorTypeModifier::SEFixedLog2LMULN2;
601         break;
602       case -1:
603         VTM = VectorTypeModifier::SEFixedLog2LMULN1;
604         break;
605       case 0:
606         VTM = VectorTypeModifier::SEFixedLog2LMUL0;
607         break;
608       case 1:
609         VTM = VectorTypeModifier::SEFixedLog2LMUL1;
610         break;
611       case 2:
612         VTM = VectorTypeModifier::SEFixedLog2LMUL2;
613         break;
614       case 3:
615         VTM = VectorTypeModifier::SEFixedLog2LMUL3;
616         break;
617       default:
618         llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
619         return std::nullopt;
620       }
621     } else if (ComplexTT.first == "Tuple") {
622       unsigned NF = 0;
623       if (ComplexTT.second.getAsInteger(10, NF)) {
624         llvm_unreachable("Invalid NF value!");
625         return std::nullopt;
626       }
627       VTM = getTupleVTM(NF);
628     } else {
629       llvm_unreachable("Illegal complex type transformers!");
630     }
631   }
632   PD.VTM = static_cast<uint8_t>(VTM);
633 
634   // Compute the remain type transformers
635   TypeModifier TM = TypeModifier::NoModifier;
636   for (char I : PrototypeDescriptorStr) {
637     switch (I) {
638     case 'P':
639       if ((TM & TypeModifier::Const) == TypeModifier::Const)
640         llvm_unreachable("'P' transformer cannot be used after 'C'");
641       if ((TM & TypeModifier::Pointer) == TypeModifier::Pointer)
642         llvm_unreachable("'P' transformer cannot be used twice");
643       TM |= TypeModifier::Pointer;
644       break;
645     case 'C':
646       TM |= TypeModifier::Const;
647       break;
648     case 'K':
649       TM |= TypeModifier::Immediate;
650       break;
651     case 'U':
652       TM |= TypeModifier::UnsignedInteger;
653       break;
654     case 'I':
655       TM |= TypeModifier::SignedInteger;
656       break;
657     case 'F':
658       TM |= TypeModifier::Float;
659       break;
660     case 'S':
661       TM |= TypeModifier::LMUL1;
662       break;
663     default:
664       llvm_unreachable("Illegal non-primitive type transformer!");
665     }
666   }
667   PD.TM = static_cast<uint8_t>(TM);
668 
669   return PD;
670 }
671 
applyModifier(const PrototypeDescriptor & Transformer)672 void RVVType::applyModifier(const PrototypeDescriptor &Transformer) {
673   // Handle primitive type transformer
674   switch (static_cast<BaseTypeModifier>(Transformer.PT)) {
675   case BaseTypeModifier::Scalar:
676     Scale = 0;
677     break;
678   case BaseTypeModifier::Vector:
679     Scale = LMUL.getScale(ElementBitwidth);
680     break;
681   case BaseTypeModifier::Void:
682     ScalarType = ScalarTypeKind::Void;
683     break;
684   case BaseTypeModifier::SizeT:
685     ScalarType = ScalarTypeKind::Size_t;
686     break;
687   case BaseTypeModifier::Ptrdiff:
688     ScalarType = ScalarTypeKind::Ptrdiff_t;
689     break;
690   case BaseTypeModifier::UnsignedLong:
691     ScalarType = ScalarTypeKind::UnsignedLong;
692     break;
693   case BaseTypeModifier::SignedLong:
694     ScalarType = ScalarTypeKind::SignedLong;
695     break;
696   case BaseTypeModifier::Float32:
697     ElementBitwidth = 32;
698     ScalarType = ScalarTypeKind::Float;
699     break;
700   case BaseTypeModifier::Invalid:
701     ScalarType = ScalarTypeKind::Invalid;
702     return;
703   }
704 
705   switch (static_cast<VectorTypeModifier>(Transformer.VTM)) {
706   case VectorTypeModifier::Widening2XVector:
707     ElementBitwidth *= 2;
708     LMUL.MulLog2LMUL(1);
709     Scale = LMUL.getScale(ElementBitwidth);
710     break;
711   case VectorTypeModifier::Widening4XVector:
712     ElementBitwidth *= 4;
713     LMUL.MulLog2LMUL(2);
714     Scale = LMUL.getScale(ElementBitwidth);
715     break;
716   case VectorTypeModifier::Widening8XVector:
717     ElementBitwidth *= 8;
718     LMUL.MulLog2LMUL(3);
719     Scale = LMUL.getScale(ElementBitwidth);
720     break;
721   case VectorTypeModifier::MaskVector:
722     ScalarType = ScalarTypeKind::Boolean;
723     Scale = LMUL.getScale(ElementBitwidth);
724     ElementBitwidth = 1;
725     break;
726   case VectorTypeModifier::Log2EEW3:
727     applyLog2EEW(3);
728     break;
729   case VectorTypeModifier::Log2EEW4:
730     applyLog2EEW(4);
731     break;
732   case VectorTypeModifier::Log2EEW5:
733     applyLog2EEW(5);
734     break;
735   case VectorTypeModifier::Log2EEW6:
736     applyLog2EEW(6);
737     break;
738   case VectorTypeModifier::FixedSEW8:
739     applyFixedSEW(8);
740     break;
741   case VectorTypeModifier::FixedSEW16:
742     applyFixedSEW(16);
743     break;
744   case VectorTypeModifier::FixedSEW32:
745     applyFixedSEW(32);
746     break;
747   case VectorTypeModifier::FixedSEW64:
748     applyFixedSEW(64);
749     break;
750   case VectorTypeModifier::LFixedLog2LMULN3:
751     applyFixedLog2LMUL(-3, FixedLMULType::LargerThan);
752     break;
753   case VectorTypeModifier::LFixedLog2LMULN2:
754     applyFixedLog2LMUL(-2, FixedLMULType::LargerThan);
755     break;
756   case VectorTypeModifier::LFixedLog2LMULN1:
757     applyFixedLog2LMUL(-1, FixedLMULType::LargerThan);
758     break;
759   case VectorTypeModifier::LFixedLog2LMUL0:
760     applyFixedLog2LMUL(0, FixedLMULType::LargerThan);
761     break;
762   case VectorTypeModifier::LFixedLog2LMUL1:
763     applyFixedLog2LMUL(1, FixedLMULType::LargerThan);
764     break;
765   case VectorTypeModifier::LFixedLog2LMUL2:
766     applyFixedLog2LMUL(2, FixedLMULType::LargerThan);
767     break;
768   case VectorTypeModifier::LFixedLog2LMUL3:
769     applyFixedLog2LMUL(3, FixedLMULType::LargerThan);
770     break;
771   case VectorTypeModifier::SFixedLog2LMULN3:
772     applyFixedLog2LMUL(-3, FixedLMULType::SmallerThan);
773     break;
774   case VectorTypeModifier::SFixedLog2LMULN2:
775     applyFixedLog2LMUL(-2, FixedLMULType::SmallerThan);
776     break;
777   case VectorTypeModifier::SFixedLog2LMULN1:
778     applyFixedLog2LMUL(-1, FixedLMULType::SmallerThan);
779     break;
780   case VectorTypeModifier::SFixedLog2LMUL0:
781     applyFixedLog2LMUL(0, FixedLMULType::SmallerThan);
782     break;
783   case VectorTypeModifier::SFixedLog2LMUL1:
784     applyFixedLog2LMUL(1, FixedLMULType::SmallerThan);
785     break;
786   case VectorTypeModifier::SFixedLog2LMUL2:
787     applyFixedLog2LMUL(2, FixedLMULType::SmallerThan);
788     break;
789   case VectorTypeModifier::SFixedLog2LMUL3:
790     applyFixedLog2LMUL(3, FixedLMULType::SmallerThan);
791     break;
792   case VectorTypeModifier::SEFixedLog2LMULN3:
793     applyFixedLog2LMUL(-3, FixedLMULType::SmallerOrEqual);
794     break;
795   case VectorTypeModifier::SEFixedLog2LMULN2:
796     applyFixedLog2LMUL(-2, FixedLMULType::SmallerOrEqual);
797     break;
798   case VectorTypeModifier::SEFixedLog2LMULN1:
799     applyFixedLog2LMUL(-1, FixedLMULType::SmallerOrEqual);
800     break;
801   case VectorTypeModifier::SEFixedLog2LMUL0:
802     applyFixedLog2LMUL(0, FixedLMULType::SmallerOrEqual);
803     break;
804   case VectorTypeModifier::SEFixedLog2LMUL1:
805     applyFixedLog2LMUL(1, FixedLMULType::SmallerOrEqual);
806     break;
807   case VectorTypeModifier::SEFixedLog2LMUL2:
808     applyFixedLog2LMUL(2, FixedLMULType::SmallerOrEqual);
809     break;
810   case VectorTypeModifier::SEFixedLog2LMUL3:
811     applyFixedLog2LMUL(3, FixedLMULType::SmallerOrEqual);
812     break;
813   case VectorTypeModifier::Tuple2:
814   case VectorTypeModifier::Tuple3:
815   case VectorTypeModifier::Tuple4:
816   case VectorTypeModifier::Tuple5:
817   case VectorTypeModifier::Tuple6:
818   case VectorTypeModifier::Tuple7:
819   case VectorTypeModifier::Tuple8: {
820     IsTuple = true;
821     NF = 2 + static_cast<uint8_t>(Transformer.VTM) -
822          static_cast<uint8_t>(VectorTypeModifier::Tuple2);
823     break;
824   }
825   case VectorTypeModifier::NoModifier:
826     break;
827   }
828 
829   // Early return if the current type modifier is already invalid.
830   if (ScalarType == Invalid)
831     return;
832 
833   for (unsigned TypeModifierMaskShift = 0;
834        TypeModifierMaskShift <= static_cast<unsigned>(TypeModifier::MaxOffset);
835        ++TypeModifierMaskShift) {
836     unsigned TypeModifierMask = 1 << TypeModifierMaskShift;
837     if ((static_cast<unsigned>(Transformer.TM) & TypeModifierMask) !=
838         TypeModifierMask)
839       continue;
840     switch (static_cast<TypeModifier>(TypeModifierMask)) {
841     case TypeModifier::Pointer:
842       IsPointer = true;
843       break;
844     case TypeModifier::Const:
845       IsConstant = true;
846       break;
847     case TypeModifier::Immediate:
848       IsImmediate = true;
849       IsConstant = true;
850       break;
851     case TypeModifier::UnsignedInteger:
852       ScalarType = ScalarTypeKind::UnsignedInteger;
853       break;
854     case TypeModifier::SignedInteger:
855       ScalarType = ScalarTypeKind::SignedInteger;
856       break;
857     case TypeModifier::Float:
858       ScalarType = ScalarTypeKind::Float;
859       break;
860     case TypeModifier::BFloat:
861       ScalarType = ScalarTypeKind::BFloat;
862       break;
863     case TypeModifier::LMUL1:
864       LMUL = LMULType(0);
865       // Update ElementBitwidth need to update Scale too.
866       Scale = LMUL.getScale(ElementBitwidth);
867       break;
868     default:
869       llvm_unreachable("Unknown type modifier mask!");
870     }
871   }
872 }
873 
applyLog2EEW(unsigned Log2EEW)874 void RVVType::applyLog2EEW(unsigned Log2EEW) {
875   // update new elmul = (eew/sew) * lmul
876   LMUL.MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth));
877   // update new eew
878   ElementBitwidth = 1 << Log2EEW;
879   ScalarType = ScalarTypeKind::SignedInteger;
880   Scale = LMUL.getScale(ElementBitwidth);
881 }
882 
applyFixedSEW(unsigned NewSEW)883 void RVVType::applyFixedSEW(unsigned NewSEW) {
884   // Set invalid type if src and dst SEW are same.
885   if (ElementBitwidth == NewSEW) {
886     ScalarType = ScalarTypeKind::Invalid;
887     return;
888   }
889   // Update new SEW
890   ElementBitwidth = NewSEW;
891   Scale = LMUL.getScale(ElementBitwidth);
892 }
893 
applyFixedLog2LMUL(int Log2LMUL,enum FixedLMULType Type)894 void RVVType::applyFixedLog2LMUL(int Log2LMUL, enum FixedLMULType Type) {
895   switch (Type) {
896   case FixedLMULType::LargerThan:
897     if (Log2LMUL <= LMUL.Log2LMUL) {
898       ScalarType = ScalarTypeKind::Invalid;
899       return;
900     }
901     break;
902   case FixedLMULType::SmallerThan:
903     if (Log2LMUL >= LMUL.Log2LMUL) {
904       ScalarType = ScalarTypeKind::Invalid;
905       return;
906     }
907     break;
908   case FixedLMULType::SmallerOrEqual:
909     if (Log2LMUL > LMUL.Log2LMUL) {
910       ScalarType = ScalarTypeKind::Invalid;
911       return;
912     }
913     break;
914   }
915 
916   // Update new LMUL
917   LMUL = LMULType(Log2LMUL);
918   Scale = LMUL.getScale(ElementBitwidth);
919 }
920 
921 std::optional<RVVTypes>
computeTypes(BasicType BT,int Log2LMUL,unsigned NF,ArrayRef<PrototypeDescriptor> Prototype)922 RVVTypeCache::computeTypes(BasicType BT, int Log2LMUL, unsigned NF,
923                            ArrayRef<PrototypeDescriptor> Prototype) {
924   RVVTypes Types;
925   for (const PrototypeDescriptor &Proto : Prototype) {
926     auto T = computeType(BT, Log2LMUL, Proto);
927     if (!T)
928       return std::nullopt;
929     // Record legal type index
930     Types.push_back(*T);
931   }
932   return Types;
933 }
934 
935 // Compute the hash value of RVVType, used for cache the result of computeType.
computeRVVTypeHashValue(BasicType BT,int Log2LMUL,PrototypeDescriptor Proto)936 static uint64_t computeRVVTypeHashValue(BasicType BT, int Log2LMUL,
937                                         PrototypeDescriptor Proto) {
938   // Layout of hash value:
939   // 0               8    16          24        32          40
940   // | Log2LMUL + 3  | BT  | Proto.PT | Proto.TM | Proto.VTM |
941   assert(Log2LMUL >= -3 && Log2LMUL <= 3);
942   return (Log2LMUL + 3) | (static_cast<uint64_t>(BT) & 0xff) << 8 |
943          ((uint64_t)(Proto.PT & 0xff) << 16) |
944          ((uint64_t)(Proto.TM & 0xff) << 24) |
945          ((uint64_t)(Proto.VTM & 0xff) << 32);
946 }
947 
computeType(BasicType BT,int Log2LMUL,PrototypeDescriptor Proto)948 std::optional<RVVTypePtr> RVVTypeCache::computeType(BasicType BT, int Log2LMUL,
949                                                     PrototypeDescriptor Proto) {
950   uint64_t Idx = computeRVVTypeHashValue(BT, Log2LMUL, Proto);
951   // Search first
952   auto It = LegalTypes.find(Idx);
953   if (It != LegalTypes.end())
954     return &(It->second);
955 
956   if (IllegalTypes.count(Idx))
957     return std::nullopt;
958 
959   // Compute type and record the result.
960   RVVType T(BT, Log2LMUL, Proto);
961   if (T.isValid()) {
962     // Record legal type index and value.
963     std::pair<std::unordered_map<uint64_t, RVVType>::iterator, bool>
964         InsertResult = LegalTypes.insert({Idx, T});
965     return &(InsertResult.first->second);
966   }
967   // Record illegal type index.
968   IllegalTypes.insert(Idx);
969   return std::nullopt;
970 }
971 
972 //===----------------------------------------------------------------------===//
973 // RVVIntrinsic implementation
974 //===----------------------------------------------------------------------===//
RVVIntrinsic(StringRef NewName,StringRef Suffix,StringRef NewOverloadedName,StringRef OverloadedSuffix,StringRef IRName,bool IsMasked,bool HasMaskedOffOperand,bool HasVL,PolicyScheme Scheme,bool SupportOverloading,bool HasBuiltinAlias,StringRef ManualCodegen,const RVVTypes & OutInTypes,const std::vector<int64_t> & NewIntrinsicTypes,unsigned NF,Policy NewPolicyAttrs,bool HasFRMRoundModeOp)975 RVVIntrinsic::RVVIntrinsic(
976     StringRef NewName, StringRef Suffix, StringRef NewOverloadedName,
977     StringRef OverloadedSuffix, StringRef IRName, bool IsMasked,
978     bool HasMaskedOffOperand, bool HasVL, PolicyScheme Scheme,
979     bool SupportOverloading, bool HasBuiltinAlias, StringRef ManualCodegen,
980     const RVVTypes &OutInTypes, const std::vector<int64_t> &NewIntrinsicTypes,
981     unsigned NF, Policy NewPolicyAttrs, bool HasFRMRoundModeOp)
982     : IRName(IRName), IsMasked(IsMasked),
983       HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme),
984       SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias),
985       ManualCodegen(ManualCodegen.str()), NF(NF), PolicyAttrs(NewPolicyAttrs) {
986 
987   // Init BuiltinName, Name and OverloadedName
988   BuiltinName = NewName.str();
989   Name = BuiltinName;
990   if (NewOverloadedName.empty())
991     OverloadedName = NewName.split("_").first.str();
992   else
993     OverloadedName = NewOverloadedName.str();
994   if (!Suffix.empty())
995     Name += "_" + Suffix.str();
996   if (!OverloadedSuffix.empty())
997     OverloadedName += "_" + OverloadedSuffix.str();
998 
999   updateNamesAndPolicy(IsMasked, hasPolicy(), Name, BuiltinName, OverloadedName,
1000                        PolicyAttrs, HasFRMRoundModeOp);
1001 
1002   // Init OutputType and InputTypes
1003   OutputType = OutInTypes[0];
1004   InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
1005 
1006   // IntrinsicTypes is unmasked TA version index. Need to update it
1007   // if there is merge operand (It is always in first operand).
1008   IntrinsicTypes = NewIntrinsicTypes;
1009   if ((IsMasked && hasMaskedOffOperand()) ||
1010       (!IsMasked && hasPassthruOperand())) {
1011     for (auto &I : IntrinsicTypes) {
1012       if (I >= 0)
1013         I += NF;
1014     }
1015   }
1016 }
1017 
getBuiltinTypeStr() const1018 std::string RVVIntrinsic::getBuiltinTypeStr() const {
1019   std::string S;
1020   S += OutputType->getBuiltinStr();
1021   for (const auto &T : InputTypes) {
1022     S += T->getBuiltinStr();
1023   }
1024   return S;
1025 }
1026 
getSuffixStr(RVVTypeCache & TypeCache,BasicType Type,int Log2LMUL,llvm::ArrayRef<PrototypeDescriptor> PrototypeDescriptors)1027 std::string RVVIntrinsic::getSuffixStr(
1028     RVVTypeCache &TypeCache, BasicType Type, int Log2LMUL,
1029     llvm::ArrayRef<PrototypeDescriptor> PrototypeDescriptors) {
1030   SmallVector<std::string> SuffixStrs;
1031   for (auto PD : PrototypeDescriptors) {
1032     auto T = TypeCache.computeType(Type, Log2LMUL, PD);
1033     SuffixStrs.push_back((*T)->getShortStr());
1034   }
1035   return join(SuffixStrs, "_");
1036 }
1037 
computeBuiltinTypes(llvm::ArrayRef<PrototypeDescriptor> Prototype,bool IsMasked,bool HasMaskedOffOperand,bool HasVL,unsigned NF,PolicyScheme DefaultScheme,Policy PolicyAttrs,bool IsTuple)1038 llvm::SmallVector<PrototypeDescriptor> RVVIntrinsic::computeBuiltinTypes(
1039     llvm::ArrayRef<PrototypeDescriptor> Prototype, bool IsMasked,
1040     bool HasMaskedOffOperand, bool HasVL, unsigned NF,
1041     PolicyScheme DefaultScheme, Policy PolicyAttrs, bool IsTuple) {
1042   SmallVector<PrototypeDescriptor> NewPrototype(Prototype.begin(),
1043                                                 Prototype.end());
1044   bool HasPassthruOp = DefaultScheme == PolicyScheme::HasPassthruOperand;
1045   if (IsMasked) {
1046     // If HasMaskedOffOperand, insert result type as first input operand if
1047     // need.
1048     if (HasMaskedOffOperand && !PolicyAttrs.isTAMAPolicy()) {
1049       if (NF == 1) {
1050         NewPrototype.insert(NewPrototype.begin() + 1, NewPrototype[0]);
1051       } else if (NF > 1) {
1052         if (IsTuple) {
1053           PrototypeDescriptor BasePtrOperand = Prototype[1];
1054           PrototypeDescriptor MaskoffType = PrototypeDescriptor(
1055               static_cast<uint8_t>(BaseTypeModifier::Vector),
1056               static_cast<uint8_t>(getTupleVTM(NF)),
1057               BasePtrOperand.TM & ~static_cast<uint8_t>(TypeModifier::Pointer));
1058           NewPrototype.insert(NewPrototype.begin() + 1, MaskoffType);
1059         } else {
1060           // Convert
1061           // (void, op0 address, op1 address, ...)
1062           // to
1063           // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
1064           PrototypeDescriptor MaskoffType = NewPrototype[1];
1065           MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer);
1066           NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1067         }
1068       }
1069     }
1070     if (HasMaskedOffOperand && NF > 1) {
1071       // Convert
1072       // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
1073       // to
1074       // (void, op0 address, op1 address, ..., mask, maskedoff0, maskedoff1,
1075       // ...)
1076       if (IsTuple)
1077         NewPrototype.insert(NewPrototype.begin() + 1,
1078                             PrototypeDescriptor::Mask);
1079       else
1080         NewPrototype.insert(NewPrototype.begin() + NF + 1,
1081                             PrototypeDescriptor::Mask);
1082     } else {
1083       // If IsMasked, insert PrototypeDescriptor:Mask as first input operand.
1084       NewPrototype.insert(NewPrototype.begin() + 1, PrototypeDescriptor::Mask);
1085     }
1086   } else {
1087     if (NF == 1) {
1088       if (PolicyAttrs.isTUPolicy() && HasPassthruOp)
1089         NewPrototype.insert(NewPrototype.begin(), NewPrototype[0]);
1090     } else if (PolicyAttrs.isTUPolicy() && HasPassthruOp) {
1091       if (IsTuple) {
1092         PrototypeDescriptor BasePtrOperand = Prototype[0];
1093         PrototypeDescriptor MaskoffType = PrototypeDescriptor(
1094             static_cast<uint8_t>(BaseTypeModifier::Vector),
1095             static_cast<uint8_t>(getTupleVTM(NF)),
1096             BasePtrOperand.TM & ~static_cast<uint8_t>(TypeModifier::Pointer));
1097         NewPrototype.insert(NewPrototype.begin(), MaskoffType);
1098       } else {
1099         // NF > 1 cases for segment load operations.
1100         // Convert
1101         // (void, op0 address, op1 address, ...)
1102         // to
1103         // (void, op0 address, op1 address, maskedoff0, maskedoff1, ...)
1104         PrototypeDescriptor MaskoffType = Prototype[1];
1105         MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer);
1106         NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1107       }
1108     }
1109  }
1110 
1111   // If HasVL, append PrototypeDescriptor:VL to last operand
1112   if (HasVL)
1113     NewPrototype.push_back(PrototypeDescriptor::VL);
1114 
1115   return NewPrototype;
1116 }
1117 
getSupportedUnMaskedPolicies()1118 llvm::SmallVector<Policy> RVVIntrinsic::getSupportedUnMaskedPolicies() {
1119   return {Policy(Policy::PolicyType::Undisturbed)}; // TU
1120 }
1121 
1122 llvm::SmallVector<Policy>
getSupportedMaskedPolicies(bool HasTailPolicy,bool HasMaskPolicy)1123 RVVIntrinsic::getSupportedMaskedPolicies(bool HasTailPolicy,
1124                                          bool HasMaskPolicy) {
1125   if (HasTailPolicy && HasMaskPolicy)
1126     return {Policy(Policy::PolicyType::Undisturbed,
1127                    Policy::PolicyType::Agnostic), // TUM
1128             Policy(Policy::PolicyType::Undisturbed,
1129                    Policy::PolicyType::Undisturbed), // TUMU
1130             Policy(Policy::PolicyType::Agnostic,
1131                    Policy::PolicyType::Undisturbed)}; // MU
1132   if (HasTailPolicy && !HasMaskPolicy)
1133     return {Policy(Policy::PolicyType::Undisturbed,
1134                    Policy::PolicyType::Agnostic)}; // TU
1135   if (!HasTailPolicy && HasMaskPolicy)
1136     return {Policy(Policy::PolicyType::Agnostic,
1137                    Policy::PolicyType::Undisturbed)}; // MU
1138   llvm_unreachable("An RVV instruction should not be without both tail policy "
1139                    "and mask policy");
1140 }
1141 
updateNamesAndPolicy(bool IsMasked,bool HasPolicy,std::string & Name,std::string & BuiltinName,std::string & OverloadedName,Policy & PolicyAttrs,bool HasFRMRoundModeOp)1142 void RVVIntrinsic::updateNamesAndPolicy(
1143     bool IsMasked, bool HasPolicy, std::string &Name, std::string &BuiltinName,
1144     std::string &OverloadedName, Policy &PolicyAttrs, bool HasFRMRoundModeOp) {
1145 
1146   auto appendPolicySuffix = [&](const std::string &suffix) {
1147     Name += suffix;
1148     BuiltinName += suffix;
1149     OverloadedName += suffix;
1150   };
1151 
1152   if (HasFRMRoundModeOp) {
1153     Name += "_rm";
1154     BuiltinName += "_rm";
1155   }
1156 
1157   if (IsMasked) {
1158     if (PolicyAttrs.isTUMUPolicy())
1159       appendPolicySuffix("_tumu");
1160     else if (PolicyAttrs.isTUMAPolicy())
1161       appendPolicySuffix("_tum");
1162     else if (PolicyAttrs.isTAMUPolicy())
1163       appendPolicySuffix("_mu");
1164     else if (PolicyAttrs.isTAMAPolicy()) {
1165       Name += "_m";
1166       BuiltinName += "_m";
1167     } else
1168       llvm_unreachable("Unhandled policy condition");
1169   } else {
1170     if (PolicyAttrs.isTUPolicy())
1171       appendPolicySuffix("_tu");
1172     else if (PolicyAttrs.isTAPolicy()) // no suffix needed
1173       return;
1174     else
1175       llvm_unreachable("Unhandled policy condition");
1176   }
1177 }
1178 
parsePrototypes(StringRef Prototypes)1179 SmallVector<PrototypeDescriptor> parsePrototypes(StringRef Prototypes) {
1180   SmallVector<PrototypeDescriptor> PrototypeDescriptors;
1181   const StringRef Primaries("evwqom0ztulf");
1182   while (!Prototypes.empty()) {
1183     size_t Idx = 0;
1184     // Skip over complex prototype because it could contain primitive type
1185     // character.
1186     if (Prototypes[0] == '(')
1187       Idx = Prototypes.find_first_of(')');
1188     Idx = Prototypes.find_first_of(Primaries, Idx);
1189     assert(Idx != StringRef::npos);
1190     auto PD = PrototypeDescriptor::parsePrototypeDescriptor(
1191         Prototypes.slice(0, Idx + 1));
1192     if (!PD)
1193       llvm_unreachable("Error during parsing prototype.");
1194     PrototypeDescriptors.push_back(*PD);
1195     Prototypes = Prototypes.drop_front(Idx + 1);
1196   }
1197   return PrototypeDescriptors;
1198 }
1199 
operator <<(raw_ostream & OS,const RVVIntrinsicRecord & Record)1200 raw_ostream &operator<<(raw_ostream &OS, const RVVIntrinsicRecord &Record) {
1201   OS << "{";
1202   OS << "\"" << Record.Name << "\",";
1203   if (Record.OverloadedName == nullptr ||
1204       StringRef(Record.OverloadedName).empty())
1205     OS << "nullptr,";
1206   else
1207     OS << "\"" << Record.OverloadedName << "\",";
1208   OS << Record.PrototypeIndex << ",";
1209   OS << Record.SuffixIndex << ",";
1210   OS << Record.OverloadedSuffixIndex << ",";
1211   OS << (int)Record.PrototypeLength << ",";
1212   OS << (int)Record.SuffixLength << ",";
1213   OS << (int)Record.OverloadedSuffixSize << ",";
1214   OS << Record.RequiredExtensions << ",";
1215   OS << (int)Record.TypeRangeMask << ",";
1216   OS << (int)Record.Log2LMULMask << ",";
1217   OS << (int)Record.NF << ",";
1218   OS << (int)Record.HasMasked << ",";
1219   OS << (int)Record.HasVL << ",";
1220   OS << (int)Record.HasMaskedOffOperand << ",";
1221   OS << (int)Record.HasTailPolicy << ",";
1222   OS << (int)Record.HasMaskPolicy << ",";
1223   OS << (int)Record.HasFRMRoundModeOp << ",";
1224   OS << (int)Record.IsTuple << ",";
1225   OS << (int)Record.UnMaskedPolicyScheme << ",";
1226   OS << (int)Record.MaskedPolicyScheme << ",";
1227   OS << "},\n";
1228   return OS;
1229 }
1230 
1231 } // end namespace RISCV
1232 } // end namespace clang
1233