xref: /freebsd-src/contrib/llvm-project/clang/lib/Support/RISCVVIntrinsicUtils.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
181ad6265SDimitry Andric //===- RISCVVIntrinsicUtils.cpp - RISC-V Vector Intrinsic Utils -*- C++ -*-===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric 
981ad6265SDimitry Andric #include "clang/Support/RISCVVIntrinsicUtils.h"
1081ad6265SDimitry Andric #include "llvm/ADT/ArrayRef.h"
1181ad6265SDimitry Andric #include "llvm/ADT/SmallSet.h"
1281ad6265SDimitry Andric #include "llvm/ADT/StringExtras.h"
1381ad6265SDimitry Andric #include "llvm/ADT/StringMap.h"
1481ad6265SDimitry Andric #include "llvm/ADT/StringSet.h"
1581ad6265SDimitry Andric #include "llvm/ADT/Twine.h"
16*bdd1243dSDimitry Andric #include "llvm/Support/ErrorHandling.h"
1781ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h"
1881ad6265SDimitry Andric #include <numeric>
19*bdd1243dSDimitry Andric #include <optional>
2081ad6265SDimitry Andric 
2181ad6265SDimitry Andric using namespace llvm;
2281ad6265SDimitry Andric 
2381ad6265SDimitry Andric namespace clang {
2481ad6265SDimitry Andric namespace RISCV {
2581ad6265SDimitry Andric 
2681ad6265SDimitry Andric const PrototypeDescriptor PrototypeDescriptor::Mask = PrototypeDescriptor(
2781ad6265SDimitry Andric     BaseTypeModifier::Vector, VectorTypeModifier::MaskVector);
2881ad6265SDimitry Andric const PrototypeDescriptor PrototypeDescriptor::VL =
2981ad6265SDimitry Andric     PrototypeDescriptor(BaseTypeModifier::SizeT);
3081ad6265SDimitry Andric const PrototypeDescriptor PrototypeDescriptor::Vector =
3181ad6265SDimitry Andric     PrototypeDescriptor(BaseTypeModifier::Vector);
3281ad6265SDimitry Andric 
3381ad6265SDimitry Andric //===----------------------------------------------------------------------===//
3481ad6265SDimitry Andric // Type implementation
3581ad6265SDimitry Andric //===----------------------------------------------------------------------===//
3681ad6265SDimitry Andric 
3781ad6265SDimitry Andric LMULType::LMULType(int NewLog2LMUL) {
3881ad6265SDimitry Andric   // Check Log2LMUL is -3, -2, -1, 0, 1, 2, 3
3981ad6265SDimitry Andric   assert(NewLog2LMUL <= 3 && NewLog2LMUL >= -3 && "Bad LMUL number!");
4081ad6265SDimitry Andric   Log2LMUL = NewLog2LMUL;
4181ad6265SDimitry Andric }
4281ad6265SDimitry Andric 
4381ad6265SDimitry Andric std::string LMULType::str() const {
4481ad6265SDimitry Andric   if (Log2LMUL < 0)
4581ad6265SDimitry Andric     return "mf" + utostr(1ULL << (-Log2LMUL));
4681ad6265SDimitry Andric   return "m" + utostr(1ULL << Log2LMUL);
4781ad6265SDimitry Andric }
4881ad6265SDimitry Andric 
4981ad6265SDimitry Andric VScaleVal LMULType::getScale(unsigned ElementBitwidth) const {
5081ad6265SDimitry Andric   int Log2ScaleResult = 0;
5181ad6265SDimitry Andric   switch (ElementBitwidth) {
5281ad6265SDimitry Andric   default:
5381ad6265SDimitry Andric     break;
5481ad6265SDimitry Andric   case 8:
5581ad6265SDimitry Andric     Log2ScaleResult = Log2LMUL + 3;
5681ad6265SDimitry Andric     break;
5781ad6265SDimitry Andric   case 16:
5881ad6265SDimitry Andric     Log2ScaleResult = Log2LMUL + 2;
5981ad6265SDimitry Andric     break;
6081ad6265SDimitry Andric   case 32:
6181ad6265SDimitry Andric     Log2ScaleResult = Log2LMUL + 1;
6281ad6265SDimitry Andric     break;
6381ad6265SDimitry Andric   case 64:
6481ad6265SDimitry Andric     Log2ScaleResult = Log2LMUL;
6581ad6265SDimitry Andric     break;
6681ad6265SDimitry Andric   }
6781ad6265SDimitry Andric   // Illegal vscale result would be less than 1
6881ad6265SDimitry Andric   if (Log2ScaleResult < 0)
69*bdd1243dSDimitry Andric     return std::nullopt;
7081ad6265SDimitry Andric   return 1 << Log2ScaleResult;
7181ad6265SDimitry Andric }
7281ad6265SDimitry Andric 
7381ad6265SDimitry Andric void LMULType::MulLog2LMUL(int log2LMUL) { Log2LMUL += log2LMUL; }
7481ad6265SDimitry Andric 
7581ad6265SDimitry Andric RVVType::RVVType(BasicType BT, int Log2LMUL,
7681ad6265SDimitry Andric                  const PrototypeDescriptor &prototype)
7781ad6265SDimitry Andric     : BT(BT), LMUL(LMULType(Log2LMUL)) {
7881ad6265SDimitry Andric   applyBasicType();
7981ad6265SDimitry Andric   applyModifier(prototype);
8081ad6265SDimitry Andric   Valid = verifyType();
8181ad6265SDimitry Andric   if (Valid) {
8281ad6265SDimitry Andric     initBuiltinStr();
8381ad6265SDimitry Andric     initTypeStr();
8481ad6265SDimitry Andric     if (isVector()) {
8581ad6265SDimitry Andric       initClangBuiltinStr();
8681ad6265SDimitry Andric     }
8781ad6265SDimitry Andric   }
8881ad6265SDimitry Andric }
8981ad6265SDimitry Andric 
9081ad6265SDimitry Andric // clang-format off
9181ad6265SDimitry Andric // boolean type are encoded the ratio of n (SEW/LMUL)
9281ad6265SDimitry Andric // SEW/LMUL | 1         | 2         | 4         | 8        | 16        | 32        | 64
9381ad6265SDimitry Andric // c type   | vbool64_t | vbool32_t | vbool16_t | vbool8_t | vbool4_t  | vbool2_t  | vbool1_t
9481ad6265SDimitry Andric // IR type  | nxv1i1    | nxv2i1    | nxv4i1    | nxv8i1   | nxv16i1   | nxv32i1   | nxv64i1
9581ad6265SDimitry Andric 
9681ad6265SDimitry Andric // type\lmul | 1/8    | 1/4      | 1/2     | 1       | 2        | 4        | 8
9781ad6265SDimitry Andric // --------  |------  | -------- | ------- | ------- | -------- | -------- | --------
9881ad6265SDimitry Andric // i64       | N/A    | N/A      | N/A     | nxv1i64 | nxv2i64  | nxv4i64  | nxv8i64
9981ad6265SDimitry Andric // i32       | N/A    | N/A      | nxv1i32 | nxv2i32 | nxv4i32  | nxv8i32  | nxv16i32
10081ad6265SDimitry Andric // i16       | N/A    | nxv1i16  | nxv2i16 | nxv4i16 | nxv8i16  | nxv16i16 | nxv32i16
10181ad6265SDimitry Andric // i8        | nxv1i8 | nxv2i8   | nxv4i8  | nxv8i8  | nxv16i8  | nxv32i8  | nxv64i8
10281ad6265SDimitry Andric // double    | N/A    | N/A      | N/A     | nxv1f64 | nxv2f64  | nxv4f64  | nxv8f64
10381ad6265SDimitry Andric // float     | N/A    | N/A      | nxv1f32 | nxv2f32 | nxv4f32  | nxv8f32  | nxv16f32
10481ad6265SDimitry Andric // half      | N/A    | nxv1f16  | nxv2f16 | nxv4f16 | nxv8f16  | nxv16f16 | nxv32f16
10581ad6265SDimitry Andric // clang-format on
10681ad6265SDimitry Andric 
10781ad6265SDimitry Andric bool RVVType::verifyType() const {
10881ad6265SDimitry Andric   if (ScalarType == Invalid)
10981ad6265SDimitry Andric     return false;
11081ad6265SDimitry Andric   if (isScalar())
11181ad6265SDimitry Andric     return true;
11281ad6265SDimitry Andric   if (!Scale)
11381ad6265SDimitry Andric     return false;
11481ad6265SDimitry Andric   if (isFloat() && ElementBitwidth == 8)
11581ad6265SDimitry Andric     return false;
116*bdd1243dSDimitry Andric   unsigned V = *Scale;
11781ad6265SDimitry Andric   switch (ElementBitwidth) {
11881ad6265SDimitry Andric   case 1:
11981ad6265SDimitry Andric   case 8:
12081ad6265SDimitry Andric     // Check Scale is 1,2,4,8,16,32,64
12181ad6265SDimitry Andric     return (V <= 64 && isPowerOf2_32(V));
12281ad6265SDimitry Andric   case 16:
12381ad6265SDimitry Andric     // Check Scale is 1,2,4,8,16,32
12481ad6265SDimitry Andric     return (V <= 32 && isPowerOf2_32(V));
12581ad6265SDimitry Andric   case 32:
12681ad6265SDimitry Andric     // Check Scale is 1,2,4,8,16
12781ad6265SDimitry Andric     return (V <= 16 && isPowerOf2_32(V));
12881ad6265SDimitry Andric   case 64:
12981ad6265SDimitry Andric     // Check Scale is 1,2,4,8
13081ad6265SDimitry Andric     return (V <= 8 && isPowerOf2_32(V));
13181ad6265SDimitry Andric   }
13281ad6265SDimitry Andric   return false;
13381ad6265SDimitry Andric }
13481ad6265SDimitry Andric 
13581ad6265SDimitry Andric void RVVType::initBuiltinStr() {
13681ad6265SDimitry Andric   assert(isValid() && "RVVType is invalid");
13781ad6265SDimitry Andric   switch (ScalarType) {
13881ad6265SDimitry Andric   case ScalarTypeKind::Void:
13981ad6265SDimitry Andric     BuiltinStr = "v";
14081ad6265SDimitry Andric     return;
14181ad6265SDimitry Andric   case ScalarTypeKind::Size_t:
14281ad6265SDimitry Andric     BuiltinStr = "z";
14381ad6265SDimitry Andric     if (IsImmediate)
14481ad6265SDimitry Andric       BuiltinStr = "I" + BuiltinStr;
14581ad6265SDimitry Andric     if (IsPointer)
14681ad6265SDimitry Andric       BuiltinStr += "*";
14781ad6265SDimitry Andric     return;
14881ad6265SDimitry Andric   case ScalarTypeKind::Ptrdiff_t:
14981ad6265SDimitry Andric     BuiltinStr = "Y";
15081ad6265SDimitry Andric     return;
15181ad6265SDimitry Andric   case ScalarTypeKind::UnsignedLong:
15281ad6265SDimitry Andric     BuiltinStr = "ULi";
15381ad6265SDimitry Andric     return;
15481ad6265SDimitry Andric   case ScalarTypeKind::SignedLong:
15581ad6265SDimitry Andric     BuiltinStr = "Li";
15681ad6265SDimitry Andric     return;
15781ad6265SDimitry Andric   case ScalarTypeKind::Boolean:
15881ad6265SDimitry Andric     assert(ElementBitwidth == 1);
15981ad6265SDimitry Andric     BuiltinStr += "b";
16081ad6265SDimitry Andric     break;
16181ad6265SDimitry Andric   case ScalarTypeKind::SignedInteger:
16281ad6265SDimitry Andric   case ScalarTypeKind::UnsignedInteger:
16381ad6265SDimitry Andric     switch (ElementBitwidth) {
16481ad6265SDimitry Andric     case 8:
16581ad6265SDimitry Andric       BuiltinStr += "c";
16681ad6265SDimitry Andric       break;
16781ad6265SDimitry Andric     case 16:
16881ad6265SDimitry Andric       BuiltinStr += "s";
16981ad6265SDimitry Andric       break;
17081ad6265SDimitry Andric     case 32:
17181ad6265SDimitry Andric       BuiltinStr += "i";
17281ad6265SDimitry Andric       break;
17381ad6265SDimitry Andric     case 64:
17481ad6265SDimitry Andric       BuiltinStr += "Wi";
17581ad6265SDimitry Andric       break;
17681ad6265SDimitry Andric     default:
17781ad6265SDimitry Andric       llvm_unreachable("Unhandled ElementBitwidth!");
17881ad6265SDimitry Andric     }
17981ad6265SDimitry Andric     if (isSignedInteger())
18081ad6265SDimitry Andric       BuiltinStr = "S" + BuiltinStr;
18181ad6265SDimitry Andric     else
18281ad6265SDimitry Andric       BuiltinStr = "U" + BuiltinStr;
18381ad6265SDimitry Andric     break;
18481ad6265SDimitry Andric   case ScalarTypeKind::Float:
18581ad6265SDimitry Andric     switch (ElementBitwidth) {
18681ad6265SDimitry Andric     case 16:
18781ad6265SDimitry Andric       BuiltinStr += "x";
18881ad6265SDimitry Andric       break;
18981ad6265SDimitry Andric     case 32:
19081ad6265SDimitry Andric       BuiltinStr += "f";
19181ad6265SDimitry Andric       break;
19281ad6265SDimitry Andric     case 64:
19381ad6265SDimitry Andric       BuiltinStr += "d";
19481ad6265SDimitry Andric       break;
19581ad6265SDimitry Andric     default:
19681ad6265SDimitry Andric       llvm_unreachable("Unhandled ElementBitwidth!");
19781ad6265SDimitry Andric     }
19881ad6265SDimitry Andric     break;
19981ad6265SDimitry Andric   default:
20081ad6265SDimitry Andric     llvm_unreachable("ScalarType is invalid!");
20181ad6265SDimitry Andric   }
20281ad6265SDimitry Andric   if (IsImmediate)
20381ad6265SDimitry Andric     BuiltinStr = "I" + BuiltinStr;
20481ad6265SDimitry Andric   if (isScalar()) {
20581ad6265SDimitry Andric     if (IsConstant)
20681ad6265SDimitry Andric       BuiltinStr += "C";
20781ad6265SDimitry Andric     if (IsPointer)
20881ad6265SDimitry Andric       BuiltinStr += "*";
20981ad6265SDimitry Andric     return;
21081ad6265SDimitry Andric   }
21181ad6265SDimitry Andric   BuiltinStr = "q" + utostr(*Scale) + BuiltinStr;
21281ad6265SDimitry Andric   // Pointer to vector types. Defined for segment load intrinsics.
21381ad6265SDimitry Andric   // segment load intrinsics have pointer type arguments to store the loaded
21481ad6265SDimitry Andric   // vector values.
21581ad6265SDimitry Andric   if (IsPointer)
21681ad6265SDimitry Andric     BuiltinStr += "*";
21781ad6265SDimitry Andric }
21881ad6265SDimitry Andric 
21981ad6265SDimitry Andric void RVVType::initClangBuiltinStr() {
22081ad6265SDimitry Andric   assert(isValid() && "RVVType is invalid");
22181ad6265SDimitry Andric   assert(isVector() && "Handle Vector type only");
22281ad6265SDimitry Andric 
22381ad6265SDimitry Andric   ClangBuiltinStr = "__rvv_";
22481ad6265SDimitry Andric   switch (ScalarType) {
22581ad6265SDimitry Andric   case ScalarTypeKind::Boolean:
22681ad6265SDimitry Andric     ClangBuiltinStr += "bool" + utostr(64 / *Scale) + "_t";
22781ad6265SDimitry Andric     return;
22881ad6265SDimitry Andric   case ScalarTypeKind::Float:
22981ad6265SDimitry Andric     ClangBuiltinStr += "float";
23081ad6265SDimitry Andric     break;
23181ad6265SDimitry Andric   case ScalarTypeKind::SignedInteger:
23281ad6265SDimitry Andric     ClangBuiltinStr += "int";
23381ad6265SDimitry Andric     break;
23481ad6265SDimitry Andric   case ScalarTypeKind::UnsignedInteger:
23581ad6265SDimitry Andric     ClangBuiltinStr += "uint";
23681ad6265SDimitry Andric     break;
23781ad6265SDimitry Andric   default:
23881ad6265SDimitry Andric     llvm_unreachable("ScalarTypeKind is invalid");
23981ad6265SDimitry Andric   }
24081ad6265SDimitry Andric   ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.str() + "_t";
24181ad6265SDimitry Andric }
24281ad6265SDimitry Andric 
24381ad6265SDimitry Andric void RVVType::initTypeStr() {
24481ad6265SDimitry Andric   assert(isValid() && "RVVType is invalid");
24581ad6265SDimitry Andric 
24681ad6265SDimitry Andric   if (IsConstant)
24781ad6265SDimitry Andric     Str += "const ";
24881ad6265SDimitry Andric 
24981ad6265SDimitry Andric   auto getTypeString = [&](StringRef TypeStr) {
25081ad6265SDimitry Andric     if (isScalar())
25181ad6265SDimitry Andric       return Twine(TypeStr + Twine(ElementBitwidth) + "_t").str();
25281ad6265SDimitry Andric     return Twine("v" + TypeStr + Twine(ElementBitwidth) + LMUL.str() + "_t")
25381ad6265SDimitry Andric         .str();
25481ad6265SDimitry Andric   };
25581ad6265SDimitry Andric 
25681ad6265SDimitry Andric   switch (ScalarType) {
25781ad6265SDimitry Andric   case ScalarTypeKind::Void:
25881ad6265SDimitry Andric     Str = "void";
25981ad6265SDimitry Andric     return;
26081ad6265SDimitry Andric   case ScalarTypeKind::Size_t:
26181ad6265SDimitry Andric     Str = "size_t";
26281ad6265SDimitry Andric     if (IsPointer)
26381ad6265SDimitry Andric       Str += " *";
26481ad6265SDimitry Andric     return;
26581ad6265SDimitry Andric   case ScalarTypeKind::Ptrdiff_t:
26681ad6265SDimitry Andric     Str = "ptrdiff_t";
26781ad6265SDimitry Andric     return;
26881ad6265SDimitry Andric   case ScalarTypeKind::UnsignedLong:
26981ad6265SDimitry Andric     Str = "unsigned long";
27081ad6265SDimitry Andric     return;
27181ad6265SDimitry Andric   case ScalarTypeKind::SignedLong:
27281ad6265SDimitry Andric     Str = "long";
27381ad6265SDimitry Andric     return;
27481ad6265SDimitry Andric   case ScalarTypeKind::Boolean:
27581ad6265SDimitry Andric     if (isScalar())
27681ad6265SDimitry Andric       Str += "bool";
27781ad6265SDimitry Andric     else
27881ad6265SDimitry Andric       // Vector bool is special case, the formulate is
27981ad6265SDimitry Andric       // `vbool<N>_t = MVT::nxv<64/N>i1` ex. vbool16_t = MVT::4i1
28081ad6265SDimitry Andric       Str += "vbool" + utostr(64 / *Scale) + "_t";
28181ad6265SDimitry Andric     break;
28281ad6265SDimitry Andric   case ScalarTypeKind::Float:
28381ad6265SDimitry Andric     if (isScalar()) {
28481ad6265SDimitry Andric       if (ElementBitwidth == 64)
28581ad6265SDimitry Andric         Str += "double";
28681ad6265SDimitry Andric       else if (ElementBitwidth == 32)
28781ad6265SDimitry Andric         Str += "float";
28881ad6265SDimitry Andric       else if (ElementBitwidth == 16)
28981ad6265SDimitry Andric         Str += "_Float16";
29081ad6265SDimitry Andric       else
29181ad6265SDimitry Andric         llvm_unreachable("Unhandled floating type.");
29281ad6265SDimitry Andric     } else
29381ad6265SDimitry Andric       Str += getTypeString("float");
29481ad6265SDimitry Andric     break;
29581ad6265SDimitry Andric   case ScalarTypeKind::SignedInteger:
29681ad6265SDimitry Andric     Str += getTypeString("int");
29781ad6265SDimitry Andric     break;
29881ad6265SDimitry Andric   case ScalarTypeKind::UnsignedInteger:
29981ad6265SDimitry Andric     Str += getTypeString("uint");
30081ad6265SDimitry Andric     break;
30181ad6265SDimitry Andric   default:
30281ad6265SDimitry Andric     llvm_unreachable("ScalarType is invalid!");
30381ad6265SDimitry Andric   }
30481ad6265SDimitry Andric   if (IsPointer)
30581ad6265SDimitry Andric     Str += " *";
30681ad6265SDimitry Andric }
30781ad6265SDimitry Andric 
30881ad6265SDimitry Andric void RVVType::initShortStr() {
30981ad6265SDimitry Andric   switch (ScalarType) {
31081ad6265SDimitry Andric   case ScalarTypeKind::Boolean:
31181ad6265SDimitry Andric     assert(isVector());
31281ad6265SDimitry Andric     ShortStr = "b" + utostr(64 / *Scale);
31381ad6265SDimitry Andric     return;
31481ad6265SDimitry Andric   case ScalarTypeKind::Float:
31581ad6265SDimitry Andric     ShortStr = "f" + utostr(ElementBitwidth);
31681ad6265SDimitry Andric     break;
31781ad6265SDimitry Andric   case ScalarTypeKind::SignedInteger:
31881ad6265SDimitry Andric     ShortStr = "i" + utostr(ElementBitwidth);
31981ad6265SDimitry Andric     break;
32081ad6265SDimitry Andric   case ScalarTypeKind::UnsignedInteger:
32181ad6265SDimitry Andric     ShortStr = "u" + utostr(ElementBitwidth);
32281ad6265SDimitry Andric     break;
32381ad6265SDimitry Andric   default:
32481ad6265SDimitry Andric     llvm_unreachable("Unhandled case!");
32581ad6265SDimitry Andric   }
32681ad6265SDimitry Andric   if (isVector())
32781ad6265SDimitry Andric     ShortStr += LMUL.str();
32881ad6265SDimitry Andric }
32981ad6265SDimitry Andric 
33081ad6265SDimitry Andric void RVVType::applyBasicType() {
33181ad6265SDimitry Andric   switch (BT) {
33281ad6265SDimitry Andric   case BasicType::Int8:
33381ad6265SDimitry Andric     ElementBitwidth = 8;
33481ad6265SDimitry Andric     ScalarType = ScalarTypeKind::SignedInteger;
33581ad6265SDimitry Andric     break;
33681ad6265SDimitry Andric   case BasicType::Int16:
33781ad6265SDimitry Andric     ElementBitwidth = 16;
33881ad6265SDimitry Andric     ScalarType = ScalarTypeKind::SignedInteger;
33981ad6265SDimitry Andric     break;
34081ad6265SDimitry Andric   case BasicType::Int32:
34181ad6265SDimitry Andric     ElementBitwidth = 32;
34281ad6265SDimitry Andric     ScalarType = ScalarTypeKind::SignedInteger;
34381ad6265SDimitry Andric     break;
34481ad6265SDimitry Andric   case BasicType::Int64:
34581ad6265SDimitry Andric     ElementBitwidth = 64;
34681ad6265SDimitry Andric     ScalarType = ScalarTypeKind::SignedInteger;
34781ad6265SDimitry Andric     break;
34881ad6265SDimitry Andric   case BasicType::Float16:
34981ad6265SDimitry Andric     ElementBitwidth = 16;
35081ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Float;
35181ad6265SDimitry Andric     break;
35281ad6265SDimitry Andric   case BasicType::Float32:
35381ad6265SDimitry Andric     ElementBitwidth = 32;
35481ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Float;
35581ad6265SDimitry Andric     break;
35681ad6265SDimitry Andric   case BasicType::Float64:
35781ad6265SDimitry Andric     ElementBitwidth = 64;
35881ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Float;
35981ad6265SDimitry Andric     break;
36081ad6265SDimitry Andric   default:
36181ad6265SDimitry Andric     llvm_unreachable("Unhandled type code!");
36281ad6265SDimitry Andric   }
36381ad6265SDimitry Andric   assert(ElementBitwidth != 0 && "Bad element bitwidth!");
36481ad6265SDimitry Andric }
36581ad6265SDimitry Andric 
366*bdd1243dSDimitry Andric std::optional<PrototypeDescriptor>
367*bdd1243dSDimitry Andric PrototypeDescriptor::parsePrototypeDescriptor(
36881ad6265SDimitry Andric     llvm::StringRef PrototypeDescriptorStr) {
36981ad6265SDimitry Andric   PrototypeDescriptor PD;
37081ad6265SDimitry Andric   BaseTypeModifier PT = BaseTypeModifier::Invalid;
37181ad6265SDimitry Andric   VectorTypeModifier VTM = VectorTypeModifier::NoModifier;
37281ad6265SDimitry Andric 
37381ad6265SDimitry Andric   if (PrototypeDescriptorStr.empty())
37481ad6265SDimitry Andric     return PD;
37581ad6265SDimitry Andric 
37681ad6265SDimitry Andric   // Handle base type modifier
37781ad6265SDimitry Andric   auto PType = PrototypeDescriptorStr.back();
37881ad6265SDimitry Andric   switch (PType) {
37981ad6265SDimitry Andric   case 'e':
38081ad6265SDimitry Andric     PT = BaseTypeModifier::Scalar;
38181ad6265SDimitry Andric     break;
38281ad6265SDimitry Andric   case 'v':
38381ad6265SDimitry Andric     PT = BaseTypeModifier::Vector;
38481ad6265SDimitry Andric     break;
38581ad6265SDimitry Andric   case 'w':
38681ad6265SDimitry Andric     PT = BaseTypeModifier::Vector;
38781ad6265SDimitry Andric     VTM = VectorTypeModifier::Widening2XVector;
38881ad6265SDimitry Andric     break;
38981ad6265SDimitry Andric   case 'q':
39081ad6265SDimitry Andric     PT = BaseTypeModifier::Vector;
39181ad6265SDimitry Andric     VTM = VectorTypeModifier::Widening4XVector;
39281ad6265SDimitry Andric     break;
39381ad6265SDimitry Andric   case 'o':
39481ad6265SDimitry Andric     PT = BaseTypeModifier::Vector;
39581ad6265SDimitry Andric     VTM = VectorTypeModifier::Widening8XVector;
39681ad6265SDimitry Andric     break;
39781ad6265SDimitry Andric   case 'm':
39881ad6265SDimitry Andric     PT = BaseTypeModifier::Vector;
39981ad6265SDimitry Andric     VTM = VectorTypeModifier::MaskVector;
40081ad6265SDimitry Andric     break;
40181ad6265SDimitry Andric   case '0':
40281ad6265SDimitry Andric     PT = BaseTypeModifier::Void;
40381ad6265SDimitry Andric     break;
40481ad6265SDimitry Andric   case 'z':
40581ad6265SDimitry Andric     PT = BaseTypeModifier::SizeT;
40681ad6265SDimitry Andric     break;
40781ad6265SDimitry Andric   case 't':
40881ad6265SDimitry Andric     PT = BaseTypeModifier::Ptrdiff;
40981ad6265SDimitry Andric     break;
41081ad6265SDimitry Andric   case 'u':
41181ad6265SDimitry Andric     PT = BaseTypeModifier::UnsignedLong;
41281ad6265SDimitry Andric     break;
41381ad6265SDimitry Andric   case 'l':
41481ad6265SDimitry Andric     PT = BaseTypeModifier::SignedLong;
41581ad6265SDimitry Andric     break;
41681ad6265SDimitry Andric   default:
41781ad6265SDimitry Andric     llvm_unreachable("Illegal primitive type transformers!");
41881ad6265SDimitry Andric   }
41981ad6265SDimitry Andric   PD.PT = static_cast<uint8_t>(PT);
42081ad6265SDimitry Andric   PrototypeDescriptorStr = PrototypeDescriptorStr.drop_back();
42181ad6265SDimitry Andric 
42281ad6265SDimitry Andric   // Compute the vector type transformers, it can only appear one time.
42381ad6265SDimitry Andric   if (PrototypeDescriptorStr.startswith("(")) {
42481ad6265SDimitry Andric     assert(VTM == VectorTypeModifier::NoModifier &&
42581ad6265SDimitry Andric            "VectorTypeModifier should only have one modifier");
42681ad6265SDimitry Andric     size_t Idx = PrototypeDescriptorStr.find(')');
42781ad6265SDimitry Andric     assert(Idx != StringRef::npos);
42881ad6265SDimitry Andric     StringRef ComplexType = PrototypeDescriptorStr.slice(1, Idx);
42981ad6265SDimitry Andric     PrototypeDescriptorStr = PrototypeDescriptorStr.drop_front(Idx + 1);
43081ad6265SDimitry Andric     assert(!PrototypeDescriptorStr.contains('(') &&
43181ad6265SDimitry Andric            "Only allow one vector type modifier");
43281ad6265SDimitry Andric 
43381ad6265SDimitry Andric     auto ComplexTT = ComplexType.split(":");
43481ad6265SDimitry Andric     if (ComplexTT.first == "Log2EEW") {
43581ad6265SDimitry Andric       uint32_t Log2EEW;
43681ad6265SDimitry Andric       if (ComplexTT.second.getAsInteger(10, Log2EEW)) {
43781ad6265SDimitry Andric         llvm_unreachable("Invalid Log2EEW value!");
438*bdd1243dSDimitry Andric         return std::nullopt;
43981ad6265SDimitry Andric       }
44081ad6265SDimitry Andric       switch (Log2EEW) {
44181ad6265SDimitry Andric       case 3:
44281ad6265SDimitry Andric         VTM = VectorTypeModifier::Log2EEW3;
44381ad6265SDimitry Andric         break;
44481ad6265SDimitry Andric       case 4:
44581ad6265SDimitry Andric         VTM = VectorTypeModifier::Log2EEW4;
44681ad6265SDimitry Andric         break;
44781ad6265SDimitry Andric       case 5:
44881ad6265SDimitry Andric         VTM = VectorTypeModifier::Log2EEW5;
44981ad6265SDimitry Andric         break;
45081ad6265SDimitry Andric       case 6:
45181ad6265SDimitry Andric         VTM = VectorTypeModifier::Log2EEW6;
45281ad6265SDimitry Andric         break;
45381ad6265SDimitry Andric       default:
45481ad6265SDimitry Andric         llvm_unreachable("Invalid Log2EEW value, should be [3-6]");
455*bdd1243dSDimitry Andric         return std::nullopt;
45681ad6265SDimitry Andric       }
45781ad6265SDimitry Andric     } else if (ComplexTT.first == "FixedSEW") {
45881ad6265SDimitry Andric       uint32_t NewSEW;
45981ad6265SDimitry Andric       if (ComplexTT.second.getAsInteger(10, NewSEW)) {
46081ad6265SDimitry Andric         llvm_unreachable("Invalid FixedSEW value!");
461*bdd1243dSDimitry Andric         return std::nullopt;
46281ad6265SDimitry Andric       }
46381ad6265SDimitry Andric       switch (NewSEW) {
46481ad6265SDimitry Andric       case 8:
46581ad6265SDimitry Andric         VTM = VectorTypeModifier::FixedSEW8;
46681ad6265SDimitry Andric         break;
46781ad6265SDimitry Andric       case 16:
46881ad6265SDimitry Andric         VTM = VectorTypeModifier::FixedSEW16;
46981ad6265SDimitry Andric         break;
47081ad6265SDimitry Andric       case 32:
47181ad6265SDimitry Andric         VTM = VectorTypeModifier::FixedSEW32;
47281ad6265SDimitry Andric         break;
47381ad6265SDimitry Andric       case 64:
47481ad6265SDimitry Andric         VTM = VectorTypeModifier::FixedSEW64;
47581ad6265SDimitry Andric         break;
47681ad6265SDimitry Andric       default:
47781ad6265SDimitry Andric         llvm_unreachable("Invalid FixedSEW value, should be 8, 16, 32 or 64");
478*bdd1243dSDimitry Andric         return std::nullopt;
47981ad6265SDimitry Andric       }
48081ad6265SDimitry Andric     } else if (ComplexTT.first == "LFixedLog2LMUL") {
48181ad6265SDimitry Andric       int32_t Log2LMUL;
48281ad6265SDimitry Andric       if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
48381ad6265SDimitry Andric         llvm_unreachable("Invalid LFixedLog2LMUL value!");
484*bdd1243dSDimitry Andric         return std::nullopt;
48581ad6265SDimitry Andric       }
48681ad6265SDimitry Andric       switch (Log2LMUL) {
48781ad6265SDimitry Andric       case -3:
48881ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMULN3;
48981ad6265SDimitry Andric         break;
49081ad6265SDimitry Andric       case -2:
49181ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMULN2;
49281ad6265SDimitry Andric         break;
49381ad6265SDimitry Andric       case -1:
49481ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMULN1;
49581ad6265SDimitry Andric         break;
49681ad6265SDimitry Andric       case 0:
49781ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMUL0;
49881ad6265SDimitry Andric         break;
49981ad6265SDimitry Andric       case 1:
50081ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMUL1;
50181ad6265SDimitry Andric         break;
50281ad6265SDimitry Andric       case 2:
50381ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMUL2;
50481ad6265SDimitry Andric         break;
50581ad6265SDimitry Andric       case 3:
50681ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMUL3;
50781ad6265SDimitry Andric         break;
50881ad6265SDimitry Andric       default:
50981ad6265SDimitry Andric         llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
510*bdd1243dSDimitry Andric         return std::nullopt;
51181ad6265SDimitry Andric       }
51281ad6265SDimitry Andric     } else if (ComplexTT.first == "SFixedLog2LMUL") {
51381ad6265SDimitry Andric       int32_t Log2LMUL;
51481ad6265SDimitry Andric       if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
51581ad6265SDimitry Andric         llvm_unreachable("Invalid SFixedLog2LMUL value!");
516*bdd1243dSDimitry Andric         return std::nullopt;
51781ad6265SDimitry Andric       }
51881ad6265SDimitry Andric       switch (Log2LMUL) {
51981ad6265SDimitry Andric       case -3:
52081ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMULN3;
52181ad6265SDimitry Andric         break;
52281ad6265SDimitry Andric       case -2:
52381ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMULN2;
52481ad6265SDimitry Andric         break;
52581ad6265SDimitry Andric       case -1:
52681ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMULN1;
52781ad6265SDimitry Andric         break;
52881ad6265SDimitry Andric       case 0:
52981ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMUL0;
53081ad6265SDimitry Andric         break;
53181ad6265SDimitry Andric       case 1:
53281ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMUL1;
53381ad6265SDimitry Andric         break;
53481ad6265SDimitry Andric       case 2:
53581ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMUL2;
53681ad6265SDimitry Andric         break;
53781ad6265SDimitry Andric       case 3:
53881ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMUL3;
53981ad6265SDimitry Andric         break;
54081ad6265SDimitry Andric       default:
54181ad6265SDimitry Andric         llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
542*bdd1243dSDimitry Andric         return std::nullopt;
54381ad6265SDimitry Andric       }
54481ad6265SDimitry Andric 
54581ad6265SDimitry Andric     } else {
54681ad6265SDimitry Andric       llvm_unreachable("Illegal complex type transformers!");
54781ad6265SDimitry Andric     }
54881ad6265SDimitry Andric   }
54981ad6265SDimitry Andric   PD.VTM = static_cast<uint8_t>(VTM);
55081ad6265SDimitry Andric 
55181ad6265SDimitry Andric   // Compute the remain type transformers
55281ad6265SDimitry Andric   TypeModifier TM = TypeModifier::NoModifier;
55381ad6265SDimitry Andric   for (char I : PrototypeDescriptorStr) {
55481ad6265SDimitry Andric     switch (I) {
55581ad6265SDimitry Andric     case 'P':
55681ad6265SDimitry Andric       if ((TM & TypeModifier::Const) == TypeModifier::Const)
55781ad6265SDimitry Andric         llvm_unreachable("'P' transformer cannot be used after 'C'");
55881ad6265SDimitry Andric       if ((TM & TypeModifier::Pointer) == TypeModifier::Pointer)
55981ad6265SDimitry Andric         llvm_unreachable("'P' transformer cannot be used twice");
56081ad6265SDimitry Andric       TM |= TypeModifier::Pointer;
56181ad6265SDimitry Andric       break;
56281ad6265SDimitry Andric     case 'C':
56381ad6265SDimitry Andric       TM |= TypeModifier::Const;
56481ad6265SDimitry Andric       break;
56581ad6265SDimitry Andric     case 'K':
56681ad6265SDimitry Andric       TM |= TypeModifier::Immediate;
56781ad6265SDimitry Andric       break;
56881ad6265SDimitry Andric     case 'U':
56981ad6265SDimitry Andric       TM |= TypeModifier::UnsignedInteger;
57081ad6265SDimitry Andric       break;
57181ad6265SDimitry Andric     case 'I':
57281ad6265SDimitry Andric       TM |= TypeModifier::SignedInteger;
57381ad6265SDimitry Andric       break;
57481ad6265SDimitry Andric     case 'F':
57581ad6265SDimitry Andric       TM |= TypeModifier::Float;
57681ad6265SDimitry Andric       break;
57781ad6265SDimitry Andric     case 'S':
57881ad6265SDimitry Andric       TM |= TypeModifier::LMUL1;
57981ad6265SDimitry Andric       break;
58081ad6265SDimitry Andric     default:
58181ad6265SDimitry Andric       llvm_unreachable("Illegal non-primitive type transformer!");
58281ad6265SDimitry Andric     }
58381ad6265SDimitry Andric   }
58481ad6265SDimitry Andric   PD.TM = static_cast<uint8_t>(TM);
58581ad6265SDimitry Andric 
58681ad6265SDimitry Andric   return PD;
58781ad6265SDimitry Andric }
58881ad6265SDimitry Andric 
58981ad6265SDimitry Andric void RVVType::applyModifier(const PrototypeDescriptor &Transformer) {
59081ad6265SDimitry Andric   // Handle primitive type transformer
59181ad6265SDimitry Andric   switch (static_cast<BaseTypeModifier>(Transformer.PT)) {
59281ad6265SDimitry Andric   case BaseTypeModifier::Scalar:
59381ad6265SDimitry Andric     Scale = 0;
59481ad6265SDimitry Andric     break;
59581ad6265SDimitry Andric   case BaseTypeModifier::Vector:
59681ad6265SDimitry Andric     Scale = LMUL.getScale(ElementBitwidth);
59781ad6265SDimitry Andric     break;
59881ad6265SDimitry Andric   case BaseTypeModifier::Void:
59981ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Void;
60081ad6265SDimitry Andric     break;
60181ad6265SDimitry Andric   case BaseTypeModifier::SizeT:
60281ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Size_t;
60381ad6265SDimitry Andric     break;
60481ad6265SDimitry Andric   case BaseTypeModifier::Ptrdiff:
60581ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Ptrdiff_t;
60681ad6265SDimitry Andric     break;
60781ad6265SDimitry Andric   case BaseTypeModifier::UnsignedLong:
60881ad6265SDimitry Andric     ScalarType = ScalarTypeKind::UnsignedLong;
60981ad6265SDimitry Andric     break;
61081ad6265SDimitry Andric   case BaseTypeModifier::SignedLong:
61181ad6265SDimitry Andric     ScalarType = ScalarTypeKind::SignedLong;
61281ad6265SDimitry Andric     break;
61381ad6265SDimitry Andric   case BaseTypeModifier::Invalid:
61481ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Invalid;
61581ad6265SDimitry Andric     return;
61681ad6265SDimitry Andric   }
61781ad6265SDimitry Andric 
61881ad6265SDimitry Andric   switch (static_cast<VectorTypeModifier>(Transformer.VTM)) {
61981ad6265SDimitry Andric   case VectorTypeModifier::Widening2XVector:
62081ad6265SDimitry Andric     ElementBitwidth *= 2;
62181ad6265SDimitry Andric     LMUL.MulLog2LMUL(1);
62281ad6265SDimitry Andric     Scale = LMUL.getScale(ElementBitwidth);
62381ad6265SDimitry Andric     break;
62481ad6265SDimitry Andric   case VectorTypeModifier::Widening4XVector:
62581ad6265SDimitry Andric     ElementBitwidth *= 4;
62681ad6265SDimitry Andric     LMUL.MulLog2LMUL(2);
62781ad6265SDimitry Andric     Scale = LMUL.getScale(ElementBitwidth);
62881ad6265SDimitry Andric     break;
62981ad6265SDimitry Andric   case VectorTypeModifier::Widening8XVector:
63081ad6265SDimitry Andric     ElementBitwidth *= 8;
63181ad6265SDimitry Andric     LMUL.MulLog2LMUL(3);
63281ad6265SDimitry Andric     Scale = LMUL.getScale(ElementBitwidth);
63381ad6265SDimitry Andric     break;
63481ad6265SDimitry Andric   case VectorTypeModifier::MaskVector:
63581ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Boolean;
63681ad6265SDimitry Andric     Scale = LMUL.getScale(ElementBitwidth);
63781ad6265SDimitry Andric     ElementBitwidth = 1;
63881ad6265SDimitry Andric     break;
63981ad6265SDimitry Andric   case VectorTypeModifier::Log2EEW3:
64081ad6265SDimitry Andric     applyLog2EEW(3);
64181ad6265SDimitry Andric     break;
64281ad6265SDimitry Andric   case VectorTypeModifier::Log2EEW4:
64381ad6265SDimitry Andric     applyLog2EEW(4);
64481ad6265SDimitry Andric     break;
64581ad6265SDimitry Andric   case VectorTypeModifier::Log2EEW5:
64681ad6265SDimitry Andric     applyLog2EEW(5);
64781ad6265SDimitry Andric     break;
64881ad6265SDimitry Andric   case VectorTypeModifier::Log2EEW6:
64981ad6265SDimitry Andric     applyLog2EEW(6);
65081ad6265SDimitry Andric     break;
65181ad6265SDimitry Andric   case VectorTypeModifier::FixedSEW8:
65281ad6265SDimitry Andric     applyFixedSEW(8);
65381ad6265SDimitry Andric     break;
65481ad6265SDimitry Andric   case VectorTypeModifier::FixedSEW16:
65581ad6265SDimitry Andric     applyFixedSEW(16);
65681ad6265SDimitry Andric     break;
65781ad6265SDimitry Andric   case VectorTypeModifier::FixedSEW32:
65881ad6265SDimitry Andric     applyFixedSEW(32);
65981ad6265SDimitry Andric     break;
66081ad6265SDimitry Andric   case VectorTypeModifier::FixedSEW64:
66181ad6265SDimitry Andric     applyFixedSEW(64);
66281ad6265SDimitry Andric     break;
66381ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMULN3:
66481ad6265SDimitry Andric     applyFixedLog2LMUL(-3, FixedLMULType::LargerThan);
66581ad6265SDimitry Andric     break;
66681ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMULN2:
66781ad6265SDimitry Andric     applyFixedLog2LMUL(-2, FixedLMULType::LargerThan);
66881ad6265SDimitry Andric     break;
66981ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMULN1:
67081ad6265SDimitry Andric     applyFixedLog2LMUL(-1, FixedLMULType::LargerThan);
67181ad6265SDimitry Andric     break;
67281ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMUL0:
67381ad6265SDimitry Andric     applyFixedLog2LMUL(0, FixedLMULType::LargerThan);
67481ad6265SDimitry Andric     break;
67581ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMUL1:
67681ad6265SDimitry Andric     applyFixedLog2LMUL(1, FixedLMULType::LargerThan);
67781ad6265SDimitry Andric     break;
67881ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMUL2:
67981ad6265SDimitry Andric     applyFixedLog2LMUL(2, FixedLMULType::LargerThan);
68081ad6265SDimitry Andric     break;
68181ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMUL3:
68281ad6265SDimitry Andric     applyFixedLog2LMUL(3, FixedLMULType::LargerThan);
68381ad6265SDimitry Andric     break;
68481ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMULN3:
68581ad6265SDimitry Andric     applyFixedLog2LMUL(-3, FixedLMULType::SmallerThan);
68681ad6265SDimitry Andric     break;
68781ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMULN2:
68881ad6265SDimitry Andric     applyFixedLog2LMUL(-2, FixedLMULType::SmallerThan);
68981ad6265SDimitry Andric     break;
69081ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMULN1:
69181ad6265SDimitry Andric     applyFixedLog2LMUL(-1, FixedLMULType::SmallerThan);
69281ad6265SDimitry Andric     break;
69381ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMUL0:
69481ad6265SDimitry Andric     applyFixedLog2LMUL(0, FixedLMULType::SmallerThan);
69581ad6265SDimitry Andric     break;
69681ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMUL1:
69781ad6265SDimitry Andric     applyFixedLog2LMUL(1, FixedLMULType::SmallerThan);
69881ad6265SDimitry Andric     break;
69981ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMUL2:
70081ad6265SDimitry Andric     applyFixedLog2LMUL(2, FixedLMULType::SmallerThan);
70181ad6265SDimitry Andric     break;
70281ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMUL3:
70381ad6265SDimitry Andric     applyFixedLog2LMUL(3, FixedLMULType::SmallerThan);
70481ad6265SDimitry Andric     break;
70581ad6265SDimitry Andric   case VectorTypeModifier::NoModifier:
70681ad6265SDimitry Andric     break;
70781ad6265SDimitry Andric   }
70881ad6265SDimitry Andric 
70981ad6265SDimitry Andric   for (unsigned TypeModifierMaskShift = 0;
71081ad6265SDimitry Andric        TypeModifierMaskShift <= static_cast<unsigned>(TypeModifier::MaxOffset);
71181ad6265SDimitry Andric        ++TypeModifierMaskShift) {
71281ad6265SDimitry Andric     unsigned TypeModifierMask = 1 << TypeModifierMaskShift;
71381ad6265SDimitry Andric     if ((static_cast<unsigned>(Transformer.TM) & TypeModifierMask) !=
71481ad6265SDimitry Andric         TypeModifierMask)
71581ad6265SDimitry Andric       continue;
71681ad6265SDimitry Andric     switch (static_cast<TypeModifier>(TypeModifierMask)) {
71781ad6265SDimitry Andric     case TypeModifier::Pointer:
71881ad6265SDimitry Andric       IsPointer = true;
71981ad6265SDimitry Andric       break;
72081ad6265SDimitry Andric     case TypeModifier::Const:
72181ad6265SDimitry Andric       IsConstant = true;
72281ad6265SDimitry Andric       break;
72381ad6265SDimitry Andric     case TypeModifier::Immediate:
72481ad6265SDimitry Andric       IsImmediate = true;
72581ad6265SDimitry Andric       IsConstant = true;
72681ad6265SDimitry Andric       break;
72781ad6265SDimitry Andric     case TypeModifier::UnsignedInteger:
72881ad6265SDimitry Andric       ScalarType = ScalarTypeKind::UnsignedInteger;
72981ad6265SDimitry Andric       break;
73081ad6265SDimitry Andric     case TypeModifier::SignedInteger:
73181ad6265SDimitry Andric       ScalarType = ScalarTypeKind::SignedInteger;
73281ad6265SDimitry Andric       break;
73381ad6265SDimitry Andric     case TypeModifier::Float:
73481ad6265SDimitry Andric       ScalarType = ScalarTypeKind::Float;
73581ad6265SDimitry Andric       break;
73681ad6265SDimitry Andric     case TypeModifier::LMUL1:
73781ad6265SDimitry Andric       LMUL = LMULType(0);
73881ad6265SDimitry Andric       // Update ElementBitwidth need to update Scale too.
73981ad6265SDimitry Andric       Scale = LMUL.getScale(ElementBitwidth);
74081ad6265SDimitry Andric       break;
74181ad6265SDimitry Andric     default:
74281ad6265SDimitry Andric       llvm_unreachable("Unknown type modifier mask!");
74381ad6265SDimitry Andric     }
74481ad6265SDimitry Andric   }
74581ad6265SDimitry Andric }
74681ad6265SDimitry Andric 
74781ad6265SDimitry Andric void RVVType::applyLog2EEW(unsigned Log2EEW) {
74881ad6265SDimitry Andric   // update new elmul = (eew/sew) * lmul
74981ad6265SDimitry Andric   LMUL.MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth));
75081ad6265SDimitry Andric   // update new eew
75181ad6265SDimitry Andric   ElementBitwidth = 1 << Log2EEW;
75281ad6265SDimitry Andric   ScalarType = ScalarTypeKind::SignedInteger;
75381ad6265SDimitry Andric   Scale = LMUL.getScale(ElementBitwidth);
75481ad6265SDimitry Andric }
75581ad6265SDimitry Andric 
75681ad6265SDimitry Andric void RVVType::applyFixedSEW(unsigned NewSEW) {
75781ad6265SDimitry Andric   // Set invalid type if src and dst SEW are same.
75881ad6265SDimitry Andric   if (ElementBitwidth == NewSEW) {
75981ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Invalid;
76081ad6265SDimitry Andric     return;
76181ad6265SDimitry Andric   }
76281ad6265SDimitry Andric   // Update new SEW
76381ad6265SDimitry Andric   ElementBitwidth = NewSEW;
76481ad6265SDimitry Andric   Scale = LMUL.getScale(ElementBitwidth);
76581ad6265SDimitry Andric }
76681ad6265SDimitry Andric 
76781ad6265SDimitry Andric void RVVType::applyFixedLog2LMUL(int Log2LMUL, enum FixedLMULType Type) {
76881ad6265SDimitry Andric   switch (Type) {
76981ad6265SDimitry Andric   case FixedLMULType::LargerThan:
77081ad6265SDimitry Andric     if (Log2LMUL < LMUL.Log2LMUL) {
77181ad6265SDimitry Andric       ScalarType = ScalarTypeKind::Invalid;
77281ad6265SDimitry Andric       return;
77381ad6265SDimitry Andric     }
77481ad6265SDimitry Andric     break;
77581ad6265SDimitry Andric   case FixedLMULType::SmallerThan:
77681ad6265SDimitry Andric     if (Log2LMUL > LMUL.Log2LMUL) {
77781ad6265SDimitry Andric       ScalarType = ScalarTypeKind::Invalid;
77881ad6265SDimitry Andric       return;
77981ad6265SDimitry Andric     }
78081ad6265SDimitry Andric     break;
78181ad6265SDimitry Andric   }
78281ad6265SDimitry Andric 
78381ad6265SDimitry Andric   // Update new LMUL
78481ad6265SDimitry Andric   LMUL = LMULType(Log2LMUL);
78581ad6265SDimitry Andric   Scale = LMUL.getScale(ElementBitwidth);
78681ad6265SDimitry Andric }
78781ad6265SDimitry Andric 
788*bdd1243dSDimitry Andric std::optional<RVVTypes>
789*bdd1243dSDimitry Andric RVVTypeCache::computeTypes(BasicType BT, int Log2LMUL, unsigned NF,
79081ad6265SDimitry Andric                            ArrayRef<PrototypeDescriptor> Prototype) {
79181ad6265SDimitry Andric   // LMUL x NF must be less than or equal to 8.
79281ad6265SDimitry Andric   if ((Log2LMUL >= 1) && (1 << Log2LMUL) * NF > 8)
793*bdd1243dSDimitry Andric     return std::nullopt;
79481ad6265SDimitry Andric 
79581ad6265SDimitry Andric   RVVTypes Types;
79681ad6265SDimitry Andric   for (const PrototypeDescriptor &Proto : Prototype) {
79781ad6265SDimitry Andric     auto T = computeType(BT, Log2LMUL, Proto);
79881ad6265SDimitry Andric     if (!T)
799*bdd1243dSDimitry Andric       return std::nullopt;
80081ad6265SDimitry Andric     // Record legal type index
801*bdd1243dSDimitry Andric     Types.push_back(*T);
80281ad6265SDimitry Andric   }
80381ad6265SDimitry Andric   return Types;
80481ad6265SDimitry Andric }
80581ad6265SDimitry Andric 
80681ad6265SDimitry Andric // Compute the hash value of RVVType, used for cache the result of computeType.
80781ad6265SDimitry Andric static uint64_t computeRVVTypeHashValue(BasicType BT, int Log2LMUL,
80881ad6265SDimitry Andric                                         PrototypeDescriptor Proto) {
80981ad6265SDimitry Andric   // Layout of hash value:
81081ad6265SDimitry Andric   // 0               8    16          24        32          40
81181ad6265SDimitry Andric   // | Log2LMUL + 3  | BT  | Proto.PT | Proto.TM | Proto.VTM |
81281ad6265SDimitry Andric   assert(Log2LMUL >= -3 && Log2LMUL <= 3);
81381ad6265SDimitry Andric   return (Log2LMUL + 3) | (static_cast<uint64_t>(BT) & 0xff) << 8 |
81481ad6265SDimitry Andric          ((uint64_t)(Proto.PT & 0xff) << 16) |
81581ad6265SDimitry Andric          ((uint64_t)(Proto.TM & 0xff) << 24) |
81681ad6265SDimitry Andric          ((uint64_t)(Proto.VTM & 0xff) << 32);
81781ad6265SDimitry Andric }
81881ad6265SDimitry Andric 
819*bdd1243dSDimitry Andric std::optional<RVVTypePtr> RVVTypeCache::computeType(BasicType BT, int Log2LMUL,
82081ad6265SDimitry Andric                                                     PrototypeDescriptor Proto) {
82181ad6265SDimitry Andric   uint64_t Idx = computeRVVTypeHashValue(BT, Log2LMUL, Proto);
82281ad6265SDimitry Andric   // Search first
82381ad6265SDimitry Andric   auto It = LegalTypes.find(Idx);
82481ad6265SDimitry Andric   if (It != LegalTypes.end())
82581ad6265SDimitry Andric     return &(It->second);
82681ad6265SDimitry Andric 
82781ad6265SDimitry Andric   if (IllegalTypes.count(Idx))
828*bdd1243dSDimitry Andric     return std::nullopt;
82981ad6265SDimitry Andric 
83081ad6265SDimitry Andric   // Compute type and record the result.
83181ad6265SDimitry Andric   RVVType T(BT, Log2LMUL, Proto);
83281ad6265SDimitry Andric   if (T.isValid()) {
83381ad6265SDimitry Andric     // Record legal type index and value.
834*bdd1243dSDimitry Andric     std::pair<std::unordered_map<uint64_t, RVVType>::iterator, bool>
835*bdd1243dSDimitry Andric         InsertResult = LegalTypes.insert({Idx, T});
836*bdd1243dSDimitry Andric     return &(InsertResult.first->second);
83781ad6265SDimitry Andric   }
83881ad6265SDimitry Andric   // Record illegal type index.
83981ad6265SDimitry Andric   IllegalTypes.insert(Idx);
840*bdd1243dSDimitry Andric   return std::nullopt;
84181ad6265SDimitry Andric }
84281ad6265SDimitry Andric 
84381ad6265SDimitry Andric //===----------------------------------------------------------------------===//
84481ad6265SDimitry Andric // RVVIntrinsic implementation
84581ad6265SDimitry Andric //===----------------------------------------------------------------------===//
846*bdd1243dSDimitry Andric RVVIntrinsic::RVVIntrinsic(StringRef NewName, StringRef Suffix,
847*bdd1243dSDimitry Andric                            StringRef NewOverloadedName,
848*bdd1243dSDimitry Andric                            StringRef OverloadedSuffix, StringRef IRName,
849*bdd1243dSDimitry Andric                            bool IsMasked, bool HasMaskedOffOperand, bool HasVL,
850*bdd1243dSDimitry Andric                            PolicyScheme Scheme, bool SupportOverloading,
851*bdd1243dSDimitry Andric                            bool HasBuiltinAlias, StringRef ManualCodegen,
852*bdd1243dSDimitry Andric                            const RVVTypes &OutInTypes,
853*bdd1243dSDimitry Andric                            const std::vector<int64_t> &NewIntrinsicTypes,
854*bdd1243dSDimitry Andric                            const std::vector<StringRef> &RequiredFeatures,
855*bdd1243dSDimitry Andric                            unsigned NF, Policy NewPolicyAttrs)
856*bdd1243dSDimitry Andric     : IRName(IRName), IsMasked(IsMasked),
857*bdd1243dSDimitry Andric       HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme),
858*bdd1243dSDimitry Andric       SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias),
859*bdd1243dSDimitry Andric       ManualCodegen(ManualCodegen.str()), NF(NF), PolicyAttrs(NewPolicyAttrs) {
86081ad6265SDimitry Andric 
86181ad6265SDimitry Andric   // Init BuiltinName, Name and OverloadedName
86281ad6265SDimitry Andric   BuiltinName = NewName.str();
86381ad6265SDimitry Andric   Name = BuiltinName;
86481ad6265SDimitry Andric   if (NewOverloadedName.empty())
86581ad6265SDimitry Andric     OverloadedName = NewName.split("_").first.str();
86681ad6265SDimitry Andric   else
86781ad6265SDimitry Andric     OverloadedName = NewOverloadedName.str();
86881ad6265SDimitry Andric   if (!Suffix.empty())
86981ad6265SDimitry Andric     Name += "_" + Suffix.str();
87081ad6265SDimitry Andric   if (!OverloadedSuffix.empty())
87181ad6265SDimitry Andric     OverloadedName += "_" + OverloadedSuffix.str();
872*bdd1243dSDimitry Andric 
873*bdd1243dSDimitry Andric   updateNamesAndPolicy(IsMasked, hasPolicy(), Name, BuiltinName, OverloadedName,
874*bdd1243dSDimitry Andric                        PolicyAttrs);
87581ad6265SDimitry Andric 
87681ad6265SDimitry Andric   // Init OutputType and InputTypes
87781ad6265SDimitry Andric   OutputType = OutInTypes[0];
87881ad6265SDimitry Andric   InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
87981ad6265SDimitry Andric 
88081ad6265SDimitry Andric   // IntrinsicTypes is unmasked TA version index. Need to update it
88181ad6265SDimitry Andric   // if there is merge operand (It is always in first operand).
88281ad6265SDimitry Andric   IntrinsicTypes = NewIntrinsicTypes;
883*bdd1243dSDimitry Andric   if ((IsMasked && hasMaskedOffOperand()) ||
88481ad6265SDimitry Andric       (!IsMasked && hasPassthruOperand())) {
88581ad6265SDimitry Andric     for (auto &I : IntrinsicTypes) {
88681ad6265SDimitry Andric       if (I >= 0)
88781ad6265SDimitry Andric         I += NF;
88881ad6265SDimitry Andric     }
88981ad6265SDimitry Andric   }
89081ad6265SDimitry Andric }
89181ad6265SDimitry Andric 
89281ad6265SDimitry Andric std::string RVVIntrinsic::getBuiltinTypeStr() const {
89381ad6265SDimitry Andric   std::string S;
89481ad6265SDimitry Andric   S += OutputType->getBuiltinStr();
89581ad6265SDimitry Andric   for (const auto &T : InputTypes) {
89681ad6265SDimitry Andric     S += T->getBuiltinStr();
89781ad6265SDimitry Andric   }
89881ad6265SDimitry Andric   return S;
89981ad6265SDimitry Andric }
90081ad6265SDimitry Andric 
90181ad6265SDimitry Andric std::string RVVIntrinsic::getSuffixStr(
902*bdd1243dSDimitry Andric     RVVTypeCache &TypeCache, BasicType Type, int Log2LMUL,
90381ad6265SDimitry Andric     llvm::ArrayRef<PrototypeDescriptor> PrototypeDescriptors) {
90481ad6265SDimitry Andric   SmallVector<std::string> SuffixStrs;
90581ad6265SDimitry Andric   for (auto PD : PrototypeDescriptors) {
906*bdd1243dSDimitry Andric     auto T = TypeCache.computeType(Type, Log2LMUL, PD);
90781ad6265SDimitry Andric     SuffixStrs.push_back((*T)->getShortStr());
90881ad6265SDimitry Andric   }
90981ad6265SDimitry Andric   return join(SuffixStrs, "_");
91081ad6265SDimitry Andric }
91181ad6265SDimitry Andric 
912*bdd1243dSDimitry Andric llvm::SmallVector<PrototypeDescriptor> RVVIntrinsic::computeBuiltinTypes(
913*bdd1243dSDimitry Andric     llvm::ArrayRef<PrototypeDescriptor> Prototype, bool IsMasked,
914*bdd1243dSDimitry Andric     bool HasMaskedOffOperand, bool HasVL, unsigned NF,
915*bdd1243dSDimitry Andric     PolicyScheme DefaultScheme, Policy PolicyAttrs) {
916972a253aSDimitry Andric   SmallVector<PrototypeDescriptor> NewPrototype(Prototype.begin(),
917972a253aSDimitry Andric                                                 Prototype.end());
918*bdd1243dSDimitry Andric   bool HasPassthruOp = DefaultScheme == PolicyScheme::HasPassthruOperand;
919972a253aSDimitry Andric   if (IsMasked) {
920*bdd1243dSDimitry Andric     // If HasMaskedOffOperand, insert result type as first input operand if
921*bdd1243dSDimitry Andric     // need.
922*bdd1243dSDimitry Andric     if (HasMaskedOffOperand && !PolicyAttrs.isTAMAPolicy()) {
923972a253aSDimitry Andric       if (NF == 1) {
924972a253aSDimitry Andric         NewPrototype.insert(NewPrototype.begin() + 1, NewPrototype[0]);
925*bdd1243dSDimitry Andric       } else if (NF > 1) {
926972a253aSDimitry Andric         // Convert
927972a253aSDimitry Andric         // (void, op0 address, op1 address, ...)
928972a253aSDimitry Andric         // to
929972a253aSDimitry Andric         // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
930972a253aSDimitry Andric         PrototypeDescriptor MaskoffType = NewPrototype[1];
931972a253aSDimitry Andric         MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer);
932*bdd1243dSDimitry Andric         NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
933972a253aSDimitry Andric       }
934972a253aSDimitry Andric     }
935972a253aSDimitry Andric     if (HasMaskedOffOperand && NF > 1) {
936972a253aSDimitry Andric       // Convert
937972a253aSDimitry Andric       // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
938972a253aSDimitry Andric       // to
939972a253aSDimitry Andric       // (void, op0 address, op1 address, ..., mask, maskedoff0, maskedoff1,
940972a253aSDimitry Andric       // ...)
941972a253aSDimitry Andric       NewPrototype.insert(NewPrototype.begin() + NF + 1,
942972a253aSDimitry Andric                           PrototypeDescriptor::Mask);
943972a253aSDimitry Andric     } else {
944972a253aSDimitry Andric       // If IsMasked, insert PrototypeDescriptor:Mask as first input operand.
945972a253aSDimitry Andric       NewPrototype.insert(NewPrototype.begin() + 1, PrototypeDescriptor::Mask);
946972a253aSDimitry Andric     }
947*bdd1243dSDimitry Andric   } else {
948*bdd1243dSDimitry Andric     if (NF == 1) {
949*bdd1243dSDimitry Andric       if (PolicyAttrs.isTUPolicy() && HasPassthruOp)
950*bdd1243dSDimitry Andric         NewPrototype.insert(NewPrototype.begin(), NewPrototype[0]);
951*bdd1243dSDimitry Andric     } else if (PolicyAttrs.isTUPolicy() && HasPassthruOp) {
952*bdd1243dSDimitry Andric       // NF > 1 cases for segment load operations.
953*bdd1243dSDimitry Andric       // Convert
954*bdd1243dSDimitry Andric       // (void, op0 address, op1 address, ...)
955*bdd1243dSDimitry Andric       // to
956*bdd1243dSDimitry Andric       // (void, op0 address, op1 address, maskedoff0, maskedoff1, ...)
957*bdd1243dSDimitry Andric       PrototypeDescriptor MaskoffType = Prototype[1];
958*bdd1243dSDimitry Andric       MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer);
959*bdd1243dSDimitry Andric       NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
960*bdd1243dSDimitry Andric     }
961972a253aSDimitry Andric  }
962972a253aSDimitry Andric 
963972a253aSDimitry Andric   // If HasVL, append PrototypeDescriptor:VL to last operand
964972a253aSDimitry Andric   if (HasVL)
965972a253aSDimitry Andric     NewPrototype.push_back(PrototypeDescriptor::VL);
966972a253aSDimitry Andric   return NewPrototype;
967972a253aSDimitry Andric }
968972a253aSDimitry Andric 
969*bdd1243dSDimitry Andric llvm::SmallVector<Policy>
970*bdd1243dSDimitry Andric RVVIntrinsic::getSupportedUnMaskedPolicies(bool HasTailPolicy,
971*bdd1243dSDimitry Andric                                            bool HasMaskPolicy) {
972*bdd1243dSDimitry Andric   return {
973*bdd1243dSDimitry Andric       Policy(Policy::PolicyType::Undisturbed, HasTailPolicy,
974*bdd1243dSDimitry Andric              HasMaskPolicy),                                               // TU
975*bdd1243dSDimitry Andric       Policy(Policy::PolicyType::Agnostic, HasTailPolicy, HasMaskPolicy)}; // TA
976*bdd1243dSDimitry Andric }
977*bdd1243dSDimitry Andric 
978*bdd1243dSDimitry Andric llvm::SmallVector<Policy>
979*bdd1243dSDimitry Andric RVVIntrinsic::getSupportedMaskedPolicies(bool HasTailPolicy,
980*bdd1243dSDimitry Andric                                          bool HasMaskPolicy) {
981*bdd1243dSDimitry Andric   if (HasTailPolicy && HasMaskPolicy)
982*bdd1243dSDimitry Andric     return {
983*bdd1243dSDimitry Andric         Policy(Policy::PolicyType::Undisturbed, Policy::PolicyType::Agnostic,
984*bdd1243dSDimitry Andric                HasTailPolicy, HasMaskPolicy), // TUMA
985*bdd1243dSDimitry Andric         Policy(Policy::PolicyType::Agnostic, Policy::PolicyType::Agnostic,
986*bdd1243dSDimitry Andric                HasTailPolicy, HasMaskPolicy), // TAMA
987*bdd1243dSDimitry Andric         Policy(Policy::PolicyType::Undisturbed, Policy::PolicyType::Undisturbed,
988*bdd1243dSDimitry Andric                HasTailPolicy, HasMaskPolicy), // TUMU
989*bdd1243dSDimitry Andric         Policy(Policy::PolicyType::Agnostic, Policy::PolicyType::Undisturbed,
990*bdd1243dSDimitry Andric                HasTailPolicy, HasMaskPolicy)}; // TAMU
991*bdd1243dSDimitry Andric   if (HasTailPolicy && !HasMaskPolicy)
992*bdd1243dSDimitry Andric     return {Policy(Policy::PolicyType::Undisturbed,
993*bdd1243dSDimitry Andric                    Policy::PolicyType::Agnostic, HasTailPolicy,
994*bdd1243dSDimitry Andric                    HasMaskPolicy), // TUM
995*bdd1243dSDimitry Andric             Policy(Policy::PolicyType::Agnostic, Policy::PolicyType::Agnostic,
996*bdd1243dSDimitry Andric                    HasTailPolicy, HasMaskPolicy)}; // TAM
997*bdd1243dSDimitry Andric   if (!HasTailPolicy && HasMaskPolicy)
998*bdd1243dSDimitry Andric     return {Policy(Policy::PolicyType::Agnostic, Policy::PolicyType::Agnostic,
999*bdd1243dSDimitry Andric                    HasTailPolicy, HasMaskPolicy), // MA
1000*bdd1243dSDimitry Andric             Policy(Policy::PolicyType::Agnostic,
1001*bdd1243dSDimitry Andric                    Policy::PolicyType::Undisturbed, HasTailPolicy,
1002*bdd1243dSDimitry Andric                    HasMaskPolicy)}; // MU
1003*bdd1243dSDimitry Andric   llvm_unreachable("An RVV instruction should not be without both tail policy "
1004*bdd1243dSDimitry Andric                    "and mask policy");
1005*bdd1243dSDimitry Andric }
1006*bdd1243dSDimitry Andric 
1007*bdd1243dSDimitry Andric void RVVIntrinsic::updateNamesAndPolicy(bool IsMasked, bool HasPolicy,
1008*bdd1243dSDimitry Andric                                         std::string &Name,
1009*bdd1243dSDimitry Andric                                         std::string &BuiltinName,
1010*bdd1243dSDimitry Andric                                         std::string &OverloadedName,
1011*bdd1243dSDimitry Andric                                         Policy &PolicyAttrs) {
1012*bdd1243dSDimitry Andric 
1013*bdd1243dSDimitry Andric   auto appendPolicySuffix = [&](const std::string &suffix) {
1014*bdd1243dSDimitry Andric     Name += suffix;
1015*bdd1243dSDimitry Andric     BuiltinName += suffix;
1016*bdd1243dSDimitry Andric     OverloadedName += suffix;
1017*bdd1243dSDimitry Andric   };
1018*bdd1243dSDimitry Andric 
1019*bdd1243dSDimitry Andric   if (PolicyAttrs.isUnspecified()) {
1020*bdd1243dSDimitry Andric     PolicyAttrs.IsUnspecified = false;
1021*bdd1243dSDimitry Andric     if (IsMasked) {
1022*bdd1243dSDimitry Andric       Name += "_m";
1023*bdd1243dSDimitry Andric       if (HasPolicy)
1024*bdd1243dSDimitry Andric         BuiltinName += "_tama";
1025*bdd1243dSDimitry Andric       else
1026*bdd1243dSDimitry Andric         BuiltinName += "_m";
1027*bdd1243dSDimitry Andric     } else {
1028*bdd1243dSDimitry Andric       if (HasPolicy)
1029*bdd1243dSDimitry Andric         BuiltinName += "_ta";
1030*bdd1243dSDimitry Andric     }
1031*bdd1243dSDimitry Andric   } else {
1032*bdd1243dSDimitry Andric     if (IsMasked) {
1033*bdd1243dSDimitry Andric       if (PolicyAttrs.isTUMAPolicy() && !PolicyAttrs.hasMaskPolicy())
1034*bdd1243dSDimitry Andric         appendPolicySuffix("_tum");
1035*bdd1243dSDimitry Andric       else if (PolicyAttrs.isTAMAPolicy() && !PolicyAttrs.hasMaskPolicy())
1036*bdd1243dSDimitry Andric         appendPolicySuffix("_tam");
1037*bdd1243dSDimitry Andric       else if (PolicyAttrs.isMUPolicy() && !PolicyAttrs.hasTailPolicy())
1038*bdd1243dSDimitry Andric         appendPolicySuffix("_mu");
1039*bdd1243dSDimitry Andric       else if (PolicyAttrs.isMAPolicy() && !PolicyAttrs.hasTailPolicy())
1040*bdd1243dSDimitry Andric         appendPolicySuffix("_ma");
1041*bdd1243dSDimitry Andric       else if (PolicyAttrs.isTUMUPolicy())
1042*bdd1243dSDimitry Andric         appendPolicySuffix("_tumu");
1043*bdd1243dSDimitry Andric       else if (PolicyAttrs.isTAMUPolicy())
1044*bdd1243dSDimitry Andric         appendPolicySuffix("_tamu");
1045*bdd1243dSDimitry Andric       else if (PolicyAttrs.isTUMAPolicy())
1046*bdd1243dSDimitry Andric         appendPolicySuffix("_tuma");
1047*bdd1243dSDimitry Andric       else if (PolicyAttrs.isTAMAPolicy())
1048*bdd1243dSDimitry Andric         appendPolicySuffix("_tama");
1049*bdd1243dSDimitry Andric       else
1050*bdd1243dSDimitry Andric         llvm_unreachable("Unhandled policy condition");
1051*bdd1243dSDimitry Andric     } else {
1052*bdd1243dSDimitry Andric       if (PolicyAttrs.isTUPolicy())
1053*bdd1243dSDimitry Andric         appendPolicySuffix("_tu");
1054*bdd1243dSDimitry Andric       else if (PolicyAttrs.isTAPolicy())
1055*bdd1243dSDimitry Andric         appendPolicySuffix("_ta");
1056*bdd1243dSDimitry Andric       else
1057*bdd1243dSDimitry Andric         llvm_unreachable("Unhandled policy condition");
1058*bdd1243dSDimitry Andric     }
1059*bdd1243dSDimitry Andric   }
1060*bdd1243dSDimitry Andric }
1061*bdd1243dSDimitry Andric 
106281ad6265SDimitry Andric SmallVector<PrototypeDescriptor> parsePrototypes(StringRef Prototypes) {
106381ad6265SDimitry Andric   SmallVector<PrototypeDescriptor> PrototypeDescriptors;
106481ad6265SDimitry Andric   const StringRef Primaries("evwqom0ztul");
106581ad6265SDimitry Andric   while (!Prototypes.empty()) {
106681ad6265SDimitry Andric     size_t Idx = 0;
106781ad6265SDimitry Andric     // Skip over complex prototype because it could contain primitive type
106881ad6265SDimitry Andric     // character.
106981ad6265SDimitry Andric     if (Prototypes[0] == '(')
107081ad6265SDimitry Andric       Idx = Prototypes.find_first_of(')');
107181ad6265SDimitry Andric     Idx = Prototypes.find_first_of(Primaries, Idx);
107281ad6265SDimitry Andric     assert(Idx != StringRef::npos);
107381ad6265SDimitry Andric     auto PD = PrototypeDescriptor::parsePrototypeDescriptor(
107481ad6265SDimitry Andric         Prototypes.slice(0, Idx + 1));
107581ad6265SDimitry Andric     if (!PD)
107681ad6265SDimitry Andric       llvm_unreachable("Error during parsing prototype.");
107781ad6265SDimitry Andric     PrototypeDescriptors.push_back(*PD);
107881ad6265SDimitry Andric     Prototypes = Prototypes.drop_front(Idx + 1);
107981ad6265SDimitry Andric   }
108081ad6265SDimitry Andric   return PrototypeDescriptors;
108181ad6265SDimitry Andric }
108281ad6265SDimitry Andric 
1083972a253aSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const RVVIntrinsicRecord &Record) {
1084972a253aSDimitry Andric   OS << "{";
1085972a253aSDimitry Andric   OS << "\"" << Record.Name << "\",";
1086972a253aSDimitry Andric   if (Record.OverloadedName == nullptr ||
1087972a253aSDimitry Andric       StringRef(Record.OverloadedName).empty())
1088972a253aSDimitry Andric     OS << "nullptr,";
1089972a253aSDimitry Andric   else
1090972a253aSDimitry Andric     OS << "\"" << Record.OverloadedName << "\",";
1091972a253aSDimitry Andric   OS << Record.PrototypeIndex << ",";
1092972a253aSDimitry Andric   OS << Record.SuffixIndex << ",";
1093972a253aSDimitry Andric   OS << Record.OverloadedSuffixIndex << ",";
1094972a253aSDimitry Andric   OS << (int)Record.PrototypeLength << ",";
1095972a253aSDimitry Andric   OS << (int)Record.SuffixLength << ",";
1096972a253aSDimitry Andric   OS << (int)Record.OverloadedSuffixSize << ",";
1097972a253aSDimitry Andric   OS << (int)Record.RequiredExtensions << ",";
1098972a253aSDimitry Andric   OS << (int)Record.TypeRangeMask << ",";
1099972a253aSDimitry Andric   OS << (int)Record.Log2LMULMask << ",";
1100972a253aSDimitry Andric   OS << (int)Record.NF << ",";
1101972a253aSDimitry Andric   OS << (int)Record.HasMasked << ",";
1102972a253aSDimitry Andric   OS << (int)Record.HasVL << ",";
1103972a253aSDimitry Andric   OS << (int)Record.HasMaskedOffOperand << ",";
1104*bdd1243dSDimitry Andric   OS << (int)Record.HasTailPolicy << ",";
1105*bdd1243dSDimitry Andric   OS << (int)Record.HasMaskPolicy << ",";
1106*bdd1243dSDimitry Andric   OS << (int)Record.UnMaskedPolicyScheme << ",";
1107*bdd1243dSDimitry Andric   OS << (int)Record.MaskedPolicyScheme << ",";
1108972a253aSDimitry Andric   OS << "},\n";
1109972a253aSDimitry Andric   return OS;
1110972a253aSDimitry Andric }
1111972a253aSDimitry Andric 
111281ad6265SDimitry Andric } // end namespace RISCV
111381ad6265SDimitry Andric } // end namespace clang
1114