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