xref: /freebsd-src/contrib/llvm-project/clang/lib/Support/RISCVVIntrinsicUtils.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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"
16bdd1243dSDimitry Andric #include "llvm/Support/ErrorHandling.h"
1781ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h"
1881ad6265SDimitry Andric #include <numeric>
19bdd1243dSDimitry 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)
69bdd1243dSDimitry 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*06c3fb27SDimitry Andric   if (IsTuple && (NF == 1 || NF > 8))
117*06c3fb27SDimitry Andric     return false;
118*06c3fb27SDimitry Andric   if (IsTuple && (1 << std::max(0, LMUL.Log2LMUL)) * NF > 8)
119*06c3fb27SDimitry Andric     return false;
120bdd1243dSDimitry Andric   unsigned V = *Scale;
12181ad6265SDimitry Andric   switch (ElementBitwidth) {
12281ad6265SDimitry Andric   case 1:
12381ad6265SDimitry Andric   case 8:
12481ad6265SDimitry Andric     // Check Scale is 1,2,4,8,16,32,64
12581ad6265SDimitry Andric     return (V <= 64 && isPowerOf2_32(V));
12681ad6265SDimitry Andric   case 16:
12781ad6265SDimitry Andric     // Check Scale is 1,2,4,8,16,32
12881ad6265SDimitry Andric     return (V <= 32 && isPowerOf2_32(V));
12981ad6265SDimitry Andric   case 32:
13081ad6265SDimitry Andric     // Check Scale is 1,2,4,8,16
13181ad6265SDimitry Andric     return (V <= 16 && isPowerOf2_32(V));
13281ad6265SDimitry Andric   case 64:
13381ad6265SDimitry Andric     // Check Scale is 1,2,4,8
13481ad6265SDimitry Andric     return (V <= 8 && isPowerOf2_32(V));
13581ad6265SDimitry Andric   }
13681ad6265SDimitry Andric   return false;
13781ad6265SDimitry Andric }
13881ad6265SDimitry Andric 
13981ad6265SDimitry Andric void RVVType::initBuiltinStr() {
14081ad6265SDimitry Andric   assert(isValid() && "RVVType is invalid");
14181ad6265SDimitry Andric   switch (ScalarType) {
14281ad6265SDimitry Andric   case ScalarTypeKind::Void:
14381ad6265SDimitry Andric     BuiltinStr = "v";
14481ad6265SDimitry Andric     return;
14581ad6265SDimitry Andric   case ScalarTypeKind::Size_t:
14681ad6265SDimitry Andric     BuiltinStr = "z";
14781ad6265SDimitry Andric     if (IsImmediate)
14881ad6265SDimitry Andric       BuiltinStr = "I" + BuiltinStr;
14981ad6265SDimitry Andric     if (IsPointer)
15081ad6265SDimitry Andric       BuiltinStr += "*";
15181ad6265SDimitry Andric     return;
15281ad6265SDimitry Andric   case ScalarTypeKind::Ptrdiff_t:
15381ad6265SDimitry Andric     BuiltinStr = "Y";
15481ad6265SDimitry Andric     return;
15581ad6265SDimitry Andric   case ScalarTypeKind::UnsignedLong:
15681ad6265SDimitry Andric     BuiltinStr = "ULi";
15781ad6265SDimitry Andric     return;
15881ad6265SDimitry Andric   case ScalarTypeKind::SignedLong:
15981ad6265SDimitry Andric     BuiltinStr = "Li";
16081ad6265SDimitry Andric     return;
16181ad6265SDimitry Andric   case ScalarTypeKind::Boolean:
16281ad6265SDimitry Andric     assert(ElementBitwidth == 1);
16381ad6265SDimitry Andric     BuiltinStr += "b";
16481ad6265SDimitry Andric     break;
16581ad6265SDimitry Andric   case ScalarTypeKind::SignedInteger:
16681ad6265SDimitry Andric   case ScalarTypeKind::UnsignedInteger:
16781ad6265SDimitry Andric     switch (ElementBitwidth) {
16881ad6265SDimitry Andric     case 8:
16981ad6265SDimitry Andric       BuiltinStr += "c";
17081ad6265SDimitry Andric       break;
17181ad6265SDimitry Andric     case 16:
17281ad6265SDimitry Andric       BuiltinStr += "s";
17381ad6265SDimitry Andric       break;
17481ad6265SDimitry Andric     case 32:
17581ad6265SDimitry Andric       BuiltinStr += "i";
17681ad6265SDimitry Andric       break;
17781ad6265SDimitry Andric     case 64:
17881ad6265SDimitry Andric       BuiltinStr += "Wi";
17981ad6265SDimitry Andric       break;
18081ad6265SDimitry Andric     default:
18181ad6265SDimitry Andric       llvm_unreachable("Unhandled ElementBitwidth!");
18281ad6265SDimitry Andric     }
18381ad6265SDimitry Andric     if (isSignedInteger())
18481ad6265SDimitry Andric       BuiltinStr = "S" + BuiltinStr;
18581ad6265SDimitry Andric     else
18681ad6265SDimitry Andric       BuiltinStr = "U" + BuiltinStr;
18781ad6265SDimitry Andric     break;
18881ad6265SDimitry Andric   case ScalarTypeKind::Float:
18981ad6265SDimitry Andric     switch (ElementBitwidth) {
19081ad6265SDimitry Andric     case 16:
19181ad6265SDimitry Andric       BuiltinStr += "x";
19281ad6265SDimitry Andric       break;
19381ad6265SDimitry Andric     case 32:
19481ad6265SDimitry Andric       BuiltinStr += "f";
19581ad6265SDimitry Andric       break;
19681ad6265SDimitry Andric     case 64:
19781ad6265SDimitry Andric       BuiltinStr += "d";
19881ad6265SDimitry Andric       break;
19981ad6265SDimitry Andric     default:
20081ad6265SDimitry Andric       llvm_unreachable("Unhandled ElementBitwidth!");
20181ad6265SDimitry Andric     }
20281ad6265SDimitry Andric     break;
20381ad6265SDimitry Andric   default:
20481ad6265SDimitry Andric     llvm_unreachable("ScalarType is invalid!");
20581ad6265SDimitry Andric   }
20681ad6265SDimitry Andric   if (IsImmediate)
20781ad6265SDimitry Andric     BuiltinStr = "I" + BuiltinStr;
20881ad6265SDimitry Andric   if (isScalar()) {
20981ad6265SDimitry Andric     if (IsConstant)
21081ad6265SDimitry Andric       BuiltinStr += "C";
21181ad6265SDimitry Andric     if (IsPointer)
21281ad6265SDimitry Andric       BuiltinStr += "*";
21381ad6265SDimitry Andric     return;
21481ad6265SDimitry Andric   }
21581ad6265SDimitry Andric   BuiltinStr = "q" + utostr(*Scale) + BuiltinStr;
21681ad6265SDimitry Andric   // Pointer to vector types. Defined for segment load intrinsics.
21781ad6265SDimitry Andric   // segment load intrinsics have pointer type arguments to store the loaded
21881ad6265SDimitry Andric   // vector values.
21981ad6265SDimitry Andric   if (IsPointer)
22081ad6265SDimitry Andric     BuiltinStr += "*";
221*06c3fb27SDimitry Andric 
222*06c3fb27SDimitry Andric   if (IsTuple)
223*06c3fb27SDimitry Andric     BuiltinStr = "T" + utostr(NF) + BuiltinStr;
22481ad6265SDimitry Andric }
22581ad6265SDimitry Andric 
22681ad6265SDimitry Andric void RVVType::initClangBuiltinStr() {
22781ad6265SDimitry Andric   assert(isValid() && "RVVType is invalid");
22881ad6265SDimitry Andric   assert(isVector() && "Handle Vector type only");
22981ad6265SDimitry Andric 
23081ad6265SDimitry Andric   ClangBuiltinStr = "__rvv_";
23181ad6265SDimitry Andric   switch (ScalarType) {
23281ad6265SDimitry Andric   case ScalarTypeKind::Boolean:
23381ad6265SDimitry Andric     ClangBuiltinStr += "bool" + utostr(64 / *Scale) + "_t";
23481ad6265SDimitry Andric     return;
23581ad6265SDimitry Andric   case ScalarTypeKind::Float:
23681ad6265SDimitry Andric     ClangBuiltinStr += "float";
23781ad6265SDimitry Andric     break;
23881ad6265SDimitry Andric   case ScalarTypeKind::SignedInteger:
23981ad6265SDimitry Andric     ClangBuiltinStr += "int";
24081ad6265SDimitry Andric     break;
24181ad6265SDimitry Andric   case ScalarTypeKind::UnsignedInteger:
24281ad6265SDimitry Andric     ClangBuiltinStr += "uint";
24381ad6265SDimitry Andric     break;
24481ad6265SDimitry Andric   default:
24581ad6265SDimitry Andric     llvm_unreachable("ScalarTypeKind is invalid");
24681ad6265SDimitry Andric   }
247*06c3fb27SDimitry Andric   ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.str() +
248*06c3fb27SDimitry Andric                      (IsTuple ? "x" + utostr(NF) : "") + "_t";
24981ad6265SDimitry Andric }
25081ad6265SDimitry Andric 
25181ad6265SDimitry Andric void RVVType::initTypeStr() {
25281ad6265SDimitry Andric   assert(isValid() && "RVVType is invalid");
25381ad6265SDimitry Andric 
25481ad6265SDimitry Andric   if (IsConstant)
25581ad6265SDimitry Andric     Str += "const ";
25681ad6265SDimitry Andric 
25781ad6265SDimitry Andric   auto getTypeString = [&](StringRef TypeStr) {
25881ad6265SDimitry Andric     if (isScalar())
25981ad6265SDimitry Andric       return Twine(TypeStr + Twine(ElementBitwidth) + "_t").str();
260*06c3fb27SDimitry Andric     return Twine("v" + TypeStr + Twine(ElementBitwidth) + LMUL.str() +
261*06c3fb27SDimitry Andric                  (IsTuple ? "x" + utostr(NF) : "") + "_t")
26281ad6265SDimitry Andric         .str();
26381ad6265SDimitry Andric   };
26481ad6265SDimitry Andric 
26581ad6265SDimitry Andric   switch (ScalarType) {
26681ad6265SDimitry Andric   case ScalarTypeKind::Void:
26781ad6265SDimitry Andric     Str = "void";
26881ad6265SDimitry Andric     return;
26981ad6265SDimitry Andric   case ScalarTypeKind::Size_t:
27081ad6265SDimitry Andric     Str = "size_t";
27181ad6265SDimitry Andric     if (IsPointer)
27281ad6265SDimitry Andric       Str += " *";
27381ad6265SDimitry Andric     return;
27481ad6265SDimitry Andric   case ScalarTypeKind::Ptrdiff_t:
27581ad6265SDimitry Andric     Str = "ptrdiff_t";
27681ad6265SDimitry Andric     return;
27781ad6265SDimitry Andric   case ScalarTypeKind::UnsignedLong:
27881ad6265SDimitry Andric     Str = "unsigned long";
27981ad6265SDimitry Andric     return;
28081ad6265SDimitry Andric   case ScalarTypeKind::SignedLong:
28181ad6265SDimitry Andric     Str = "long";
28281ad6265SDimitry Andric     return;
28381ad6265SDimitry Andric   case ScalarTypeKind::Boolean:
28481ad6265SDimitry Andric     if (isScalar())
28581ad6265SDimitry Andric       Str += "bool";
28681ad6265SDimitry Andric     else
28781ad6265SDimitry Andric       // Vector bool is special case, the formulate is
28881ad6265SDimitry Andric       // `vbool<N>_t = MVT::nxv<64/N>i1` ex. vbool16_t = MVT::4i1
28981ad6265SDimitry Andric       Str += "vbool" + utostr(64 / *Scale) + "_t";
29081ad6265SDimitry Andric     break;
29181ad6265SDimitry Andric   case ScalarTypeKind::Float:
29281ad6265SDimitry Andric     if (isScalar()) {
29381ad6265SDimitry Andric       if (ElementBitwidth == 64)
29481ad6265SDimitry Andric         Str += "double";
29581ad6265SDimitry Andric       else if (ElementBitwidth == 32)
29681ad6265SDimitry Andric         Str += "float";
29781ad6265SDimitry Andric       else if (ElementBitwidth == 16)
29881ad6265SDimitry Andric         Str += "_Float16";
29981ad6265SDimitry Andric       else
30081ad6265SDimitry Andric         llvm_unreachable("Unhandled floating type.");
30181ad6265SDimitry Andric     } else
30281ad6265SDimitry Andric       Str += getTypeString("float");
30381ad6265SDimitry Andric     break;
30481ad6265SDimitry Andric   case ScalarTypeKind::SignedInteger:
30581ad6265SDimitry Andric     Str += getTypeString("int");
30681ad6265SDimitry Andric     break;
30781ad6265SDimitry Andric   case ScalarTypeKind::UnsignedInteger:
30881ad6265SDimitry Andric     Str += getTypeString("uint");
30981ad6265SDimitry Andric     break;
31081ad6265SDimitry Andric   default:
31181ad6265SDimitry Andric     llvm_unreachable("ScalarType is invalid!");
31281ad6265SDimitry Andric   }
31381ad6265SDimitry Andric   if (IsPointer)
31481ad6265SDimitry Andric     Str += " *";
31581ad6265SDimitry Andric }
31681ad6265SDimitry Andric 
31781ad6265SDimitry Andric void RVVType::initShortStr() {
31881ad6265SDimitry Andric   switch (ScalarType) {
31981ad6265SDimitry Andric   case ScalarTypeKind::Boolean:
32081ad6265SDimitry Andric     assert(isVector());
32181ad6265SDimitry Andric     ShortStr = "b" + utostr(64 / *Scale);
32281ad6265SDimitry Andric     return;
32381ad6265SDimitry Andric   case ScalarTypeKind::Float:
32481ad6265SDimitry Andric     ShortStr = "f" + utostr(ElementBitwidth);
32581ad6265SDimitry Andric     break;
32681ad6265SDimitry Andric   case ScalarTypeKind::SignedInteger:
32781ad6265SDimitry Andric     ShortStr = "i" + utostr(ElementBitwidth);
32881ad6265SDimitry Andric     break;
32981ad6265SDimitry Andric   case ScalarTypeKind::UnsignedInteger:
33081ad6265SDimitry Andric     ShortStr = "u" + utostr(ElementBitwidth);
33181ad6265SDimitry Andric     break;
33281ad6265SDimitry Andric   default:
33381ad6265SDimitry Andric     llvm_unreachable("Unhandled case!");
33481ad6265SDimitry Andric   }
33581ad6265SDimitry Andric   if (isVector())
33681ad6265SDimitry Andric     ShortStr += LMUL.str();
337*06c3fb27SDimitry Andric   if (isTuple())
338*06c3fb27SDimitry Andric     ShortStr += "x" + utostr(NF);
339*06c3fb27SDimitry Andric }
340*06c3fb27SDimitry Andric 
341*06c3fb27SDimitry Andric static VectorTypeModifier getTupleVTM(unsigned NF) {
342*06c3fb27SDimitry Andric   assert(2 <= NF && NF <= 8 && "2 <= NF <= 8");
343*06c3fb27SDimitry Andric   return static_cast<VectorTypeModifier>(
344*06c3fb27SDimitry Andric       static_cast<uint8_t>(VectorTypeModifier::Tuple2) + (NF - 2));
34581ad6265SDimitry Andric }
34681ad6265SDimitry Andric 
34781ad6265SDimitry Andric void RVVType::applyBasicType() {
34881ad6265SDimitry Andric   switch (BT) {
34981ad6265SDimitry Andric   case BasicType::Int8:
35081ad6265SDimitry Andric     ElementBitwidth = 8;
35181ad6265SDimitry Andric     ScalarType = ScalarTypeKind::SignedInteger;
35281ad6265SDimitry Andric     break;
35381ad6265SDimitry Andric   case BasicType::Int16:
35481ad6265SDimitry Andric     ElementBitwidth = 16;
35581ad6265SDimitry Andric     ScalarType = ScalarTypeKind::SignedInteger;
35681ad6265SDimitry Andric     break;
35781ad6265SDimitry Andric   case BasicType::Int32:
35881ad6265SDimitry Andric     ElementBitwidth = 32;
35981ad6265SDimitry Andric     ScalarType = ScalarTypeKind::SignedInteger;
36081ad6265SDimitry Andric     break;
36181ad6265SDimitry Andric   case BasicType::Int64:
36281ad6265SDimitry Andric     ElementBitwidth = 64;
36381ad6265SDimitry Andric     ScalarType = ScalarTypeKind::SignedInteger;
36481ad6265SDimitry Andric     break;
36581ad6265SDimitry Andric   case BasicType::Float16:
36681ad6265SDimitry Andric     ElementBitwidth = 16;
36781ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Float;
36881ad6265SDimitry Andric     break;
36981ad6265SDimitry Andric   case BasicType::Float32:
37081ad6265SDimitry Andric     ElementBitwidth = 32;
37181ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Float;
37281ad6265SDimitry Andric     break;
37381ad6265SDimitry Andric   case BasicType::Float64:
37481ad6265SDimitry Andric     ElementBitwidth = 64;
37581ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Float;
37681ad6265SDimitry Andric     break;
37781ad6265SDimitry Andric   default:
37881ad6265SDimitry Andric     llvm_unreachable("Unhandled type code!");
37981ad6265SDimitry Andric   }
38081ad6265SDimitry Andric   assert(ElementBitwidth != 0 && "Bad element bitwidth!");
38181ad6265SDimitry Andric }
38281ad6265SDimitry Andric 
383bdd1243dSDimitry Andric std::optional<PrototypeDescriptor>
384bdd1243dSDimitry Andric PrototypeDescriptor::parsePrototypeDescriptor(
38581ad6265SDimitry Andric     llvm::StringRef PrototypeDescriptorStr) {
38681ad6265SDimitry Andric   PrototypeDescriptor PD;
38781ad6265SDimitry Andric   BaseTypeModifier PT = BaseTypeModifier::Invalid;
38881ad6265SDimitry Andric   VectorTypeModifier VTM = VectorTypeModifier::NoModifier;
38981ad6265SDimitry Andric 
39081ad6265SDimitry Andric   if (PrototypeDescriptorStr.empty())
39181ad6265SDimitry Andric     return PD;
39281ad6265SDimitry Andric 
39381ad6265SDimitry Andric   // Handle base type modifier
39481ad6265SDimitry Andric   auto PType = PrototypeDescriptorStr.back();
39581ad6265SDimitry Andric   switch (PType) {
39681ad6265SDimitry Andric   case 'e':
39781ad6265SDimitry Andric     PT = BaseTypeModifier::Scalar;
39881ad6265SDimitry Andric     break;
39981ad6265SDimitry Andric   case 'v':
40081ad6265SDimitry Andric     PT = BaseTypeModifier::Vector;
40181ad6265SDimitry Andric     break;
40281ad6265SDimitry Andric   case 'w':
40381ad6265SDimitry Andric     PT = BaseTypeModifier::Vector;
40481ad6265SDimitry Andric     VTM = VectorTypeModifier::Widening2XVector;
40581ad6265SDimitry Andric     break;
40681ad6265SDimitry Andric   case 'q':
40781ad6265SDimitry Andric     PT = BaseTypeModifier::Vector;
40881ad6265SDimitry Andric     VTM = VectorTypeModifier::Widening4XVector;
40981ad6265SDimitry Andric     break;
41081ad6265SDimitry Andric   case 'o':
41181ad6265SDimitry Andric     PT = BaseTypeModifier::Vector;
41281ad6265SDimitry Andric     VTM = VectorTypeModifier::Widening8XVector;
41381ad6265SDimitry Andric     break;
41481ad6265SDimitry Andric   case 'm':
41581ad6265SDimitry Andric     PT = BaseTypeModifier::Vector;
41681ad6265SDimitry Andric     VTM = VectorTypeModifier::MaskVector;
41781ad6265SDimitry Andric     break;
41881ad6265SDimitry Andric   case '0':
41981ad6265SDimitry Andric     PT = BaseTypeModifier::Void;
42081ad6265SDimitry Andric     break;
42181ad6265SDimitry Andric   case 'z':
42281ad6265SDimitry Andric     PT = BaseTypeModifier::SizeT;
42381ad6265SDimitry Andric     break;
42481ad6265SDimitry Andric   case 't':
42581ad6265SDimitry Andric     PT = BaseTypeModifier::Ptrdiff;
42681ad6265SDimitry Andric     break;
42781ad6265SDimitry Andric   case 'u':
42881ad6265SDimitry Andric     PT = BaseTypeModifier::UnsignedLong;
42981ad6265SDimitry Andric     break;
43081ad6265SDimitry Andric   case 'l':
43181ad6265SDimitry Andric     PT = BaseTypeModifier::SignedLong;
43281ad6265SDimitry Andric     break;
43381ad6265SDimitry Andric   default:
43481ad6265SDimitry Andric     llvm_unreachable("Illegal primitive type transformers!");
43581ad6265SDimitry Andric   }
43681ad6265SDimitry Andric   PD.PT = static_cast<uint8_t>(PT);
43781ad6265SDimitry Andric   PrototypeDescriptorStr = PrototypeDescriptorStr.drop_back();
43881ad6265SDimitry Andric 
43981ad6265SDimitry Andric   // Compute the vector type transformers, it can only appear one time.
44081ad6265SDimitry Andric   if (PrototypeDescriptorStr.startswith("(")) {
44181ad6265SDimitry Andric     assert(VTM == VectorTypeModifier::NoModifier &&
44281ad6265SDimitry Andric            "VectorTypeModifier should only have one modifier");
44381ad6265SDimitry Andric     size_t Idx = PrototypeDescriptorStr.find(')');
44481ad6265SDimitry Andric     assert(Idx != StringRef::npos);
44581ad6265SDimitry Andric     StringRef ComplexType = PrototypeDescriptorStr.slice(1, Idx);
44681ad6265SDimitry Andric     PrototypeDescriptorStr = PrototypeDescriptorStr.drop_front(Idx + 1);
44781ad6265SDimitry Andric     assert(!PrototypeDescriptorStr.contains('(') &&
44881ad6265SDimitry Andric            "Only allow one vector type modifier");
44981ad6265SDimitry Andric 
45081ad6265SDimitry Andric     auto ComplexTT = ComplexType.split(":");
45181ad6265SDimitry Andric     if (ComplexTT.first == "Log2EEW") {
45281ad6265SDimitry Andric       uint32_t Log2EEW;
45381ad6265SDimitry Andric       if (ComplexTT.second.getAsInteger(10, Log2EEW)) {
45481ad6265SDimitry Andric         llvm_unreachable("Invalid Log2EEW value!");
455bdd1243dSDimitry Andric         return std::nullopt;
45681ad6265SDimitry Andric       }
45781ad6265SDimitry Andric       switch (Log2EEW) {
45881ad6265SDimitry Andric       case 3:
45981ad6265SDimitry Andric         VTM = VectorTypeModifier::Log2EEW3;
46081ad6265SDimitry Andric         break;
46181ad6265SDimitry Andric       case 4:
46281ad6265SDimitry Andric         VTM = VectorTypeModifier::Log2EEW4;
46381ad6265SDimitry Andric         break;
46481ad6265SDimitry Andric       case 5:
46581ad6265SDimitry Andric         VTM = VectorTypeModifier::Log2EEW5;
46681ad6265SDimitry Andric         break;
46781ad6265SDimitry Andric       case 6:
46881ad6265SDimitry Andric         VTM = VectorTypeModifier::Log2EEW6;
46981ad6265SDimitry Andric         break;
47081ad6265SDimitry Andric       default:
47181ad6265SDimitry Andric         llvm_unreachable("Invalid Log2EEW value, should be [3-6]");
472bdd1243dSDimitry Andric         return std::nullopt;
47381ad6265SDimitry Andric       }
47481ad6265SDimitry Andric     } else if (ComplexTT.first == "FixedSEW") {
47581ad6265SDimitry Andric       uint32_t NewSEW;
47681ad6265SDimitry Andric       if (ComplexTT.second.getAsInteger(10, NewSEW)) {
47781ad6265SDimitry Andric         llvm_unreachable("Invalid FixedSEW value!");
478bdd1243dSDimitry Andric         return std::nullopt;
47981ad6265SDimitry Andric       }
48081ad6265SDimitry Andric       switch (NewSEW) {
48181ad6265SDimitry Andric       case 8:
48281ad6265SDimitry Andric         VTM = VectorTypeModifier::FixedSEW8;
48381ad6265SDimitry Andric         break;
48481ad6265SDimitry Andric       case 16:
48581ad6265SDimitry Andric         VTM = VectorTypeModifier::FixedSEW16;
48681ad6265SDimitry Andric         break;
48781ad6265SDimitry Andric       case 32:
48881ad6265SDimitry Andric         VTM = VectorTypeModifier::FixedSEW32;
48981ad6265SDimitry Andric         break;
49081ad6265SDimitry Andric       case 64:
49181ad6265SDimitry Andric         VTM = VectorTypeModifier::FixedSEW64;
49281ad6265SDimitry Andric         break;
49381ad6265SDimitry Andric       default:
49481ad6265SDimitry Andric         llvm_unreachable("Invalid FixedSEW value, should be 8, 16, 32 or 64");
495bdd1243dSDimitry Andric         return std::nullopt;
49681ad6265SDimitry Andric       }
49781ad6265SDimitry Andric     } else if (ComplexTT.first == "LFixedLog2LMUL") {
49881ad6265SDimitry Andric       int32_t Log2LMUL;
49981ad6265SDimitry Andric       if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
50081ad6265SDimitry Andric         llvm_unreachable("Invalid LFixedLog2LMUL value!");
501bdd1243dSDimitry Andric         return std::nullopt;
50281ad6265SDimitry Andric       }
50381ad6265SDimitry Andric       switch (Log2LMUL) {
50481ad6265SDimitry Andric       case -3:
50581ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMULN3;
50681ad6265SDimitry Andric         break;
50781ad6265SDimitry Andric       case -2:
50881ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMULN2;
50981ad6265SDimitry Andric         break;
51081ad6265SDimitry Andric       case -1:
51181ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMULN1;
51281ad6265SDimitry Andric         break;
51381ad6265SDimitry Andric       case 0:
51481ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMUL0;
51581ad6265SDimitry Andric         break;
51681ad6265SDimitry Andric       case 1:
51781ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMUL1;
51881ad6265SDimitry Andric         break;
51981ad6265SDimitry Andric       case 2:
52081ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMUL2;
52181ad6265SDimitry Andric         break;
52281ad6265SDimitry Andric       case 3:
52381ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMUL3;
52481ad6265SDimitry Andric         break;
52581ad6265SDimitry Andric       default:
52681ad6265SDimitry Andric         llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
527bdd1243dSDimitry Andric         return std::nullopt;
52881ad6265SDimitry Andric       }
52981ad6265SDimitry Andric     } else if (ComplexTT.first == "SFixedLog2LMUL") {
53081ad6265SDimitry Andric       int32_t Log2LMUL;
53181ad6265SDimitry Andric       if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
53281ad6265SDimitry Andric         llvm_unreachable("Invalid SFixedLog2LMUL value!");
533bdd1243dSDimitry Andric         return std::nullopt;
53481ad6265SDimitry Andric       }
53581ad6265SDimitry Andric       switch (Log2LMUL) {
53681ad6265SDimitry Andric       case -3:
53781ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMULN3;
53881ad6265SDimitry Andric         break;
53981ad6265SDimitry Andric       case -2:
54081ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMULN2;
54181ad6265SDimitry Andric         break;
54281ad6265SDimitry Andric       case -1:
54381ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMULN1;
54481ad6265SDimitry Andric         break;
54581ad6265SDimitry Andric       case 0:
54681ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMUL0;
54781ad6265SDimitry Andric         break;
54881ad6265SDimitry Andric       case 1:
54981ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMUL1;
55081ad6265SDimitry Andric         break;
55181ad6265SDimitry Andric       case 2:
55281ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMUL2;
55381ad6265SDimitry Andric         break;
55481ad6265SDimitry Andric       case 3:
55581ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMUL3;
55681ad6265SDimitry Andric         break;
55781ad6265SDimitry Andric       default:
55881ad6265SDimitry Andric         llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
559bdd1243dSDimitry Andric         return std::nullopt;
56081ad6265SDimitry Andric       }
56181ad6265SDimitry Andric 
562*06c3fb27SDimitry Andric     } else if (ComplexTT.first == "Tuple") {
563*06c3fb27SDimitry Andric       unsigned NF = 0;
564*06c3fb27SDimitry Andric       if (ComplexTT.second.getAsInteger(10, NF)) {
565*06c3fb27SDimitry Andric         llvm_unreachable("Invalid NF value!");
566*06c3fb27SDimitry Andric         return std::nullopt;
567*06c3fb27SDimitry Andric       }
568*06c3fb27SDimitry Andric       VTM = getTupleVTM(NF);
56981ad6265SDimitry Andric     } else {
57081ad6265SDimitry Andric       llvm_unreachable("Illegal complex type transformers!");
57181ad6265SDimitry Andric     }
57281ad6265SDimitry Andric   }
57381ad6265SDimitry Andric   PD.VTM = static_cast<uint8_t>(VTM);
57481ad6265SDimitry Andric 
57581ad6265SDimitry Andric   // Compute the remain type transformers
57681ad6265SDimitry Andric   TypeModifier TM = TypeModifier::NoModifier;
57781ad6265SDimitry Andric   for (char I : PrototypeDescriptorStr) {
57881ad6265SDimitry Andric     switch (I) {
57981ad6265SDimitry Andric     case 'P':
58081ad6265SDimitry Andric       if ((TM & TypeModifier::Const) == TypeModifier::Const)
58181ad6265SDimitry Andric         llvm_unreachable("'P' transformer cannot be used after 'C'");
58281ad6265SDimitry Andric       if ((TM & TypeModifier::Pointer) == TypeModifier::Pointer)
58381ad6265SDimitry Andric         llvm_unreachable("'P' transformer cannot be used twice");
58481ad6265SDimitry Andric       TM |= TypeModifier::Pointer;
58581ad6265SDimitry Andric       break;
58681ad6265SDimitry Andric     case 'C':
58781ad6265SDimitry Andric       TM |= TypeModifier::Const;
58881ad6265SDimitry Andric       break;
58981ad6265SDimitry Andric     case 'K':
59081ad6265SDimitry Andric       TM |= TypeModifier::Immediate;
59181ad6265SDimitry Andric       break;
59281ad6265SDimitry Andric     case 'U':
59381ad6265SDimitry Andric       TM |= TypeModifier::UnsignedInteger;
59481ad6265SDimitry Andric       break;
59581ad6265SDimitry Andric     case 'I':
59681ad6265SDimitry Andric       TM |= TypeModifier::SignedInteger;
59781ad6265SDimitry Andric       break;
59881ad6265SDimitry Andric     case 'F':
59981ad6265SDimitry Andric       TM |= TypeModifier::Float;
60081ad6265SDimitry Andric       break;
60181ad6265SDimitry Andric     case 'S':
60281ad6265SDimitry Andric       TM |= TypeModifier::LMUL1;
60381ad6265SDimitry Andric       break;
60481ad6265SDimitry Andric     default:
60581ad6265SDimitry Andric       llvm_unreachable("Illegal non-primitive type transformer!");
60681ad6265SDimitry Andric     }
60781ad6265SDimitry Andric   }
60881ad6265SDimitry Andric   PD.TM = static_cast<uint8_t>(TM);
60981ad6265SDimitry Andric 
61081ad6265SDimitry Andric   return PD;
61181ad6265SDimitry Andric }
61281ad6265SDimitry Andric 
61381ad6265SDimitry Andric void RVVType::applyModifier(const PrototypeDescriptor &Transformer) {
61481ad6265SDimitry Andric   // Handle primitive type transformer
61581ad6265SDimitry Andric   switch (static_cast<BaseTypeModifier>(Transformer.PT)) {
61681ad6265SDimitry Andric   case BaseTypeModifier::Scalar:
61781ad6265SDimitry Andric     Scale = 0;
61881ad6265SDimitry Andric     break;
61981ad6265SDimitry Andric   case BaseTypeModifier::Vector:
62081ad6265SDimitry Andric     Scale = LMUL.getScale(ElementBitwidth);
62181ad6265SDimitry Andric     break;
62281ad6265SDimitry Andric   case BaseTypeModifier::Void:
62381ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Void;
62481ad6265SDimitry Andric     break;
62581ad6265SDimitry Andric   case BaseTypeModifier::SizeT:
62681ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Size_t;
62781ad6265SDimitry Andric     break;
62881ad6265SDimitry Andric   case BaseTypeModifier::Ptrdiff:
62981ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Ptrdiff_t;
63081ad6265SDimitry Andric     break;
63181ad6265SDimitry Andric   case BaseTypeModifier::UnsignedLong:
63281ad6265SDimitry Andric     ScalarType = ScalarTypeKind::UnsignedLong;
63381ad6265SDimitry Andric     break;
63481ad6265SDimitry Andric   case BaseTypeModifier::SignedLong:
63581ad6265SDimitry Andric     ScalarType = ScalarTypeKind::SignedLong;
63681ad6265SDimitry Andric     break;
63781ad6265SDimitry Andric   case BaseTypeModifier::Invalid:
63881ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Invalid;
63981ad6265SDimitry Andric     return;
64081ad6265SDimitry Andric   }
64181ad6265SDimitry Andric 
64281ad6265SDimitry Andric   switch (static_cast<VectorTypeModifier>(Transformer.VTM)) {
64381ad6265SDimitry Andric   case VectorTypeModifier::Widening2XVector:
64481ad6265SDimitry Andric     ElementBitwidth *= 2;
64581ad6265SDimitry Andric     LMUL.MulLog2LMUL(1);
64681ad6265SDimitry Andric     Scale = LMUL.getScale(ElementBitwidth);
64781ad6265SDimitry Andric     break;
64881ad6265SDimitry Andric   case VectorTypeModifier::Widening4XVector:
64981ad6265SDimitry Andric     ElementBitwidth *= 4;
65081ad6265SDimitry Andric     LMUL.MulLog2LMUL(2);
65181ad6265SDimitry Andric     Scale = LMUL.getScale(ElementBitwidth);
65281ad6265SDimitry Andric     break;
65381ad6265SDimitry Andric   case VectorTypeModifier::Widening8XVector:
65481ad6265SDimitry Andric     ElementBitwidth *= 8;
65581ad6265SDimitry Andric     LMUL.MulLog2LMUL(3);
65681ad6265SDimitry Andric     Scale = LMUL.getScale(ElementBitwidth);
65781ad6265SDimitry Andric     break;
65881ad6265SDimitry Andric   case VectorTypeModifier::MaskVector:
65981ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Boolean;
66081ad6265SDimitry Andric     Scale = LMUL.getScale(ElementBitwidth);
66181ad6265SDimitry Andric     ElementBitwidth = 1;
66281ad6265SDimitry Andric     break;
66381ad6265SDimitry Andric   case VectorTypeModifier::Log2EEW3:
66481ad6265SDimitry Andric     applyLog2EEW(3);
66581ad6265SDimitry Andric     break;
66681ad6265SDimitry Andric   case VectorTypeModifier::Log2EEW4:
66781ad6265SDimitry Andric     applyLog2EEW(4);
66881ad6265SDimitry Andric     break;
66981ad6265SDimitry Andric   case VectorTypeModifier::Log2EEW5:
67081ad6265SDimitry Andric     applyLog2EEW(5);
67181ad6265SDimitry Andric     break;
67281ad6265SDimitry Andric   case VectorTypeModifier::Log2EEW6:
67381ad6265SDimitry Andric     applyLog2EEW(6);
67481ad6265SDimitry Andric     break;
67581ad6265SDimitry Andric   case VectorTypeModifier::FixedSEW8:
67681ad6265SDimitry Andric     applyFixedSEW(8);
67781ad6265SDimitry Andric     break;
67881ad6265SDimitry Andric   case VectorTypeModifier::FixedSEW16:
67981ad6265SDimitry Andric     applyFixedSEW(16);
68081ad6265SDimitry Andric     break;
68181ad6265SDimitry Andric   case VectorTypeModifier::FixedSEW32:
68281ad6265SDimitry Andric     applyFixedSEW(32);
68381ad6265SDimitry Andric     break;
68481ad6265SDimitry Andric   case VectorTypeModifier::FixedSEW64:
68581ad6265SDimitry Andric     applyFixedSEW(64);
68681ad6265SDimitry Andric     break;
68781ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMULN3:
68881ad6265SDimitry Andric     applyFixedLog2LMUL(-3, FixedLMULType::LargerThan);
68981ad6265SDimitry Andric     break;
69081ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMULN2:
69181ad6265SDimitry Andric     applyFixedLog2LMUL(-2, FixedLMULType::LargerThan);
69281ad6265SDimitry Andric     break;
69381ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMULN1:
69481ad6265SDimitry Andric     applyFixedLog2LMUL(-1, FixedLMULType::LargerThan);
69581ad6265SDimitry Andric     break;
69681ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMUL0:
69781ad6265SDimitry Andric     applyFixedLog2LMUL(0, FixedLMULType::LargerThan);
69881ad6265SDimitry Andric     break;
69981ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMUL1:
70081ad6265SDimitry Andric     applyFixedLog2LMUL(1, FixedLMULType::LargerThan);
70181ad6265SDimitry Andric     break;
70281ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMUL2:
70381ad6265SDimitry Andric     applyFixedLog2LMUL(2, FixedLMULType::LargerThan);
70481ad6265SDimitry Andric     break;
70581ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMUL3:
70681ad6265SDimitry Andric     applyFixedLog2LMUL(3, FixedLMULType::LargerThan);
70781ad6265SDimitry Andric     break;
70881ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMULN3:
70981ad6265SDimitry Andric     applyFixedLog2LMUL(-3, FixedLMULType::SmallerThan);
71081ad6265SDimitry Andric     break;
71181ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMULN2:
71281ad6265SDimitry Andric     applyFixedLog2LMUL(-2, FixedLMULType::SmallerThan);
71381ad6265SDimitry Andric     break;
71481ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMULN1:
71581ad6265SDimitry Andric     applyFixedLog2LMUL(-1, FixedLMULType::SmallerThan);
71681ad6265SDimitry Andric     break;
71781ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMUL0:
71881ad6265SDimitry Andric     applyFixedLog2LMUL(0, FixedLMULType::SmallerThan);
71981ad6265SDimitry Andric     break;
72081ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMUL1:
72181ad6265SDimitry Andric     applyFixedLog2LMUL(1, FixedLMULType::SmallerThan);
72281ad6265SDimitry Andric     break;
72381ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMUL2:
72481ad6265SDimitry Andric     applyFixedLog2LMUL(2, FixedLMULType::SmallerThan);
72581ad6265SDimitry Andric     break;
72681ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMUL3:
72781ad6265SDimitry Andric     applyFixedLog2LMUL(3, FixedLMULType::SmallerThan);
72881ad6265SDimitry Andric     break;
729*06c3fb27SDimitry Andric   case VectorTypeModifier::Tuple2:
730*06c3fb27SDimitry Andric   case VectorTypeModifier::Tuple3:
731*06c3fb27SDimitry Andric   case VectorTypeModifier::Tuple4:
732*06c3fb27SDimitry Andric   case VectorTypeModifier::Tuple5:
733*06c3fb27SDimitry Andric   case VectorTypeModifier::Tuple6:
734*06c3fb27SDimitry Andric   case VectorTypeModifier::Tuple7:
735*06c3fb27SDimitry Andric   case VectorTypeModifier::Tuple8: {
736*06c3fb27SDimitry Andric     IsTuple = true;
737*06c3fb27SDimitry Andric     NF = 2 + static_cast<uint8_t>(Transformer.VTM) -
738*06c3fb27SDimitry Andric          static_cast<uint8_t>(VectorTypeModifier::Tuple2);
739*06c3fb27SDimitry Andric     break;
740*06c3fb27SDimitry Andric   }
74181ad6265SDimitry Andric   case VectorTypeModifier::NoModifier:
74281ad6265SDimitry Andric     break;
74381ad6265SDimitry Andric   }
74481ad6265SDimitry Andric 
74581ad6265SDimitry Andric   for (unsigned TypeModifierMaskShift = 0;
74681ad6265SDimitry Andric        TypeModifierMaskShift <= static_cast<unsigned>(TypeModifier::MaxOffset);
74781ad6265SDimitry Andric        ++TypeModifierMaskShift) {
74881ad6265SDimitry Andric     unsigned TypeModifierMask = 1 << TypeModifierMaskShift;
74981ad6265SDimitry Andric     if ((static_cast<unsigned>(Transformer.TM) & TypeModifierMask) !=
75081ad6265SDimitry Andric         TypeModifierMask)
75181ad6265SDimitry Andric       continue;
75281ad6265SDimitry Andric     switch (static_cast<TypeModifier>(TypeModifierMask)) {
75381ad6265SDimitry Andric     case TypeModifier::Pointer:
75481ad6265SDimitry Andric       IsPointer = true;
75581ad6265SDimitry Andric       break;
75681ad6265SDimitry Andric     case TypeModifier::Const:
75781ad6265SDimitry Andric       IsConstant = true;
75881ad6265SDimitry Andric       break;
75981ad6265SDimitry Andric     case TypeModifier::Immediate:
76081ad6265SDimitry Andric       IsImmediate = true;
76181ad6265SDimitry Andric       IsConstant = true;
76281ad6265SDimitry Andric       break;
76381ad6265SDimitry Andric     case TypeModifier::UnsignedInteger:
76481ad6265SDimitry Andric       ScalarType = ScalarTypeKind::UnsignedInteger;
76581ad6265SDimitry Andric       break;
76681ad6265SDimitry Andric     case TypeModifier::SignedInteger:
76781ad6265SDimitry Andric       ScalarType = ScalarTypeKind::SignedInteger;
76881ad6265SDimitry Andric       break;
76981ad6265SDimitry Andric     case TypeModifier::Float:
77081ad6265SDimitry Andric       ScalarType = ScalarTypeKind::Float;
77181ad6265SDimitry Andric       break;
77281ad6265SDimitry Andric     case TypeModifier::LMUL1:
77381ad6265SDimitry Andric       LMUL = LMULType(0);
77481ad6265SDimitry Andric       // Update ElementBitwidth need to update Scale too.
77581ad6265SDimitry Andric       Scale = LMUL.getScale(ElementBitwidth);
77681ad6265SDimitry Andric       break;
77781ad6265SDimitry Andric     default:
77881ad6265SDimitry Andric       llvm_unreachable("Unknown type modifier mask!");
77981ad6265SDimitry Andric     }
78081ad6265SDimitry Andric   }
78181ad6265SDimitry Andric }
78281ad6265SDimitry Andric 
78381ad6265SDimitry Andric void RVVType::applyLog2EEW(unsigned Log2EEW) {
78481ad6265SDimitry Andric   // update new elmul = (eew/sew) * lmul
78581ad6265SDimitry Andric   LMUL.MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth));
78681ad6265SDimitry Andric   // update new eew
78781ad6265SDimitry Andric   ElementBitwidth = 1 << Log2EEW;
78881ad6265SDimitry Andric   ScalarType = ScalarTypeKind::SignedInteger;
78981ad6265SDimitry Andric   Scale = LMUL.getScale(ElementBitwidth);
79081ad6265SDimitry Andric }
79181ad6265SDimitry Andric 
79281ad6265SDimitry Andric void RVVType::applyFixedSEW(unsigned NewSEW) {
79381ad6265SDimitry Andric   // Set invalid type if src and dst SEW are same.
79481ad6265SDimitry Andric   if (ElementBitwidth == NewSEW) {
79581ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Invalid;
79681ad6265SDimitry Andric     return;
79781ad6265SDimitry Andric   }
79881ad6265SDimitry Andric   // Update new SEW
79981ad6265SDimitry Andric   ElementBitwidth = NewSEW;
80081ad6265SDimitry Andric   Scale = LMUL.getScale(ElementBitwidth);
80181ad6265SDimitry Andric }
80281ad6265SDimitry Andric 
80381ad6265SDimitry Andric void RVVType::applyFixedLog2LMUL(int Log2LMUL, enum FixedLMULType Type) {
80481ad6265SDimitry Andric   switch (Type) {
80581ad6265SDimitry Andric   case FixedLMULType::LargerThan:
80681ad6265SDimitry Andric     if (Log2LMUL < LMUL.Log2LMUL) {
80781ad6265SDimitry Andric       ScalarType = ScalarTypeKind::Invalid;
80881ad6265SDimitry Andric       return;
80981ad6265SDimitry Andric     }
81081ad6265SDimitry Andric     break;
81181ad6265SDimitry Andric   case FixedLMULType::SmallerThan:
81281ad6265SDimitry Andric     if (Log2LMUL > LMUL.Log2LMUL) {
81381ad6265SDimitry Andric       ScalarType = ScalarTypeKind::Invalid;
81481ad6265SDimitry Andric       return;
81581ad6265SDimitry Andric     }
81681ad6265SDimitry Andric     break;
81781ad6265SDimitry Andric   }
81881ad6265SDimitry Andric 
81981ad6265SDimitry Andric   // Update new LMUL
82081ad6265SDimitry Andric   LMUL = LMULType(Log2LMUL);
82181ad6265SDimitry Andric   Scale = LMUL.getScale(ElementBitwidth);
82281ad6265SDimitry Andric }
82381ad6265SDimitry Andric 
824bdd1243dSDimitry Andric std::optional<RVVTypes>
825bdd1243dSDimitry Andric RVVTypeCache::computeTypes(BasicType BT, int Log2LMUL, unsigned NF,
82681ad6265SDimitry Andric                            ArrayRef<PrototypeDescriptor> Prototype) {
82781ad6265SDimitry Andric   RVVTypes Types;
82881ad6265SDimitry Andric   for (const PrototypeDescriptor &Proto : Prototype) {
82981ad6265SDimitry Andric     auto T = computeType(BT, Log2LMUL, Proto);
83081ad6265SDimitry Andric     if (!T)
831bdd1243dSDimitry Andric       return std::nullopt;
83281ad6265SDimitry Andric     // Record legal type index
833bdd1243dSDimitry Andric     Types.push_back(*T);
83481ad6265SDimitry Andric   }
83581ad6265SDimitry Andric   return Types;
83681ad6265SDimitry Andric }
83781ad6265SDimitry Andric 
83881ad6265SDimitry Andric // Compute the hash value of RVVType, used for cache the result of computeType.
83981ad6265SDimitry Andric static uint64_t computeRVVTypeHashValue(BasicType BT, int Log2LMUL,
84081ad6265SDimitry Andric                                         PrototypeDescriptor Proto) {
84181ad6265SDimitry Andric   // Layout of hash value:
84281ad6265SDimitry Andric   // 0               8    16          24        32          40
84381ad6265SDimitry Andric   // | Log2LMUL + 3  | BT  | Proto.PT | Proto.TM | Proto.VTM |
84481ad6265SDimitry Andric   assert(Log2LMUL >= -3 && Log2LMUL <= 3);
84581ad6265SDimitry Andric   return (Log2LMUL + 3) | (static_cast<uint64_t>(BT) & 0xff) << 8 |
84681ad6265SDimitry Andric          ((uint64_t)(Proto.PT & 0xff) << 16) |
84781ad6265SDimitry Andric          ((uint64_t)(Proto.TM & 0xff) << 24) |
84881ad6265SDimitry Andric          ((uint64_t)(Proto.VTM & 0xff) << 32);
84981ad6265SDimitry Andric }
85081ad6265SDimitry Andric 
851bdd1243dSDimitry Andric std::optional<RVVTypePtr> RVVTypeCache::computeType(BasicType BT, int Log2LMUL,
85281ad6265SDimitry Andric                                                     PrototypeDescriptor Proto) {
85381ad6265SDimitry Andric   uint64_t Idx = computeRVVTypeHashValue(BT, Log2LMUL, Proto);
85481ad6265SDimitry Andric   // Search first
85581ad6265SDimitry Andric   auto It = LegalTypes.find(Idx);
85681ad6265SDimitry Andric   if (It != LegalTypes.end())
85781ad6265SDimitry Andric     return &(It->second);
85881ad6265SDimitry Andric 
85981ad6265SDimitry Andric   if (IllegalTypes.count(Idx))
860bdd1243dSDimitry Andric     return std::nullopt;
86181ad6265SDimitry Andric 
86281ad6265SDimitry Andric   // Compute type and record the result.
86381ad6265SDimitry Andric   RVVType T(BT, Log2LMUL, Proto);
86481ad6265SDimitry Andric   if (T.isValid()) {
86581ad6265SDimitry Andric     // Record legal type index and value.
866bdd1243dSDimitry Andric     std::pair<std::unordered_map<uint64_t, RVVType>::iterator, bool>
867bdd1243dSDimitry Andric         InsertResult = LegalTypes.insert({Idx, T});
868bdd1243dSDimitry Andric     return &(InsertResult.first->second);
86981ad6265SDimitry Andric   }
87081ad6265SDimitry Andric   // Record illegal type index.
87181ad6265SDimitry Andric   IllegalTypes.insert(Idx);
872bdd1243dSDimitry Andric   return std::nullopt;
87381ad6265SDimitry Andric }
87481ad6265SDimitry Andric 
87581ad6265SDimitry Andric //===----------------------------------------------------------------------===//
87681ad6265SDimitry Andric // RVVIntrinsic implementation
87781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
878*06c3fb27SDimitry Andric RVVIntrinsic::RVVIntrinsic(
879*06c3fb27SDimitry Andric     StringRef NewName, StringRef Suffix, StringRef NewOverloadedName,
880*06c3fb27SDimitry Andric     StringRef OverloadedSuffix, StringRef IRName, bool IsMasked,
881*06c3fb27SDimitry Andric     bool HasMaskedOffOperand, bool HasVL, PolicyScheme Scheme,
882*06c3fb27SDimitry Andric     bool SupportOverloading, bool HasBuiltinAlias, StringRef ManualCodegen,
883*06c3fb27SDimitry Andric     const RVVTypes &OutInTypes, const std::vector<int64_t> &NewIntrinsicTypes,
884*06c3fb27SDimitry Andric     const std::vector<StringRef> &RequiredFeatures, unsigned NF,
885*06c3fb27SDimitry Andric     Policy NewPolicyAttrs, bool HasFRMRoundModeOp)
886bdd1243dSDimitry Andric     : IRName(IRName), IsMasked(IsMasked),
887bdd1243dSDimitry Andric       HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme),
888bdd1243dSDimitry Andric       SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias),
889bdd1243dSDimitry Andric       ManualCodegen(ManualCodegen.str()), NF(NF), PolicyAttrs(NewPolicyAttrs) {
89081ad6265SDimitry Andric 
89181ad6265SDimitry Andric   // Init BuiltinName, Name and OverloadedName
89281ad6265SDimitry Andric   BuiltinName = NewName.str();
89381ad6265SDimitry Andric   Name = BuiltinName;
89481ad6265SDimitry Andric   if (NewOverloadedName.empty())
89581ad6265SDimitry Andric     OverloadedName = NewName.split("_").first.str();
89681ad6265SDimitry Andric   else
89781ad6265SDimitry Andric     OverloadedName = NewOverloadedName.str();
89881ad6265SDimitry Andric   if (!Suffix.empty())
89981ad6265SDimitry Andric     Name += "_" + Suffix.str();
90081ad6265SDimitry Andric   if (!OverloadedSuffix.empty())
90181ad6265SDimitry Andric     OverloadedName += "_" + OverloadedSuffix.str();
902bdd1243dSDimitry Andric 
903bdd1243dSDimitry Andric   updateNamesAndPolicy(IsMasked, hasPolicy(), Name, BuiltinName, OverloadedName,
904*06c3fb27SDimitry Andric                        PolicyAttrs, HasFRMRoundModeOp);
90581ad6265SDimitry Andric 
90681ad6265SDimitry Andric   // Init OutputType and InputTypes
90781ad6265SDimitry Andric   OutputType = OutInTypes[0];
90881ad6265SDimitry Andric   InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
90981ad6265SDimitry Andric 
91081ad6265SDimitry Andric   // IntrinsicTypes is unmasked TA version index. Need to update it
91181ad6265SDimitry Andric   // if there is merge operand (It is always in first operand).
91281ad6265SDimitry Andric   IntrinsicTypes = NewIntrinsicTypes;
913bdd1243dSDimitry Andric   if ((IsMasked && hasMaskedOffOperand()) ||
91481ad6265SDimitry Andric       (!IsMasked && hasPassthruOperand())) {
91581ad6265SDimitry Andric     for (auto &I : IntrinsicTypes) {
91681ad6265SDimitry Andric       if (I >= 0)
91781ad6265SDimitry Andric         I += NF;
91881ad6265SDimitry Andric     }
91981ad6265SDimitry Andric   }
92081ad6265SDimitry Andric }
92181ad6265SDimitry Andric 
92281ad6265SDimitry Andric std::string RVVIntrinsic::getBuiltinTypeStr() const {
92381ad6265SDimitry Andric   std::string S;
92481ad6265SDimitry Andric   S += OutputType->getBuiltinStr();
92581ad6265SDimitry Andric   for (const auto &T : InputTypes) {
92681ad6265SDimitry Andric     S += T->getBuiltinStr();
92781ad6265SDimitry Andric   }
92881ad6265SDimitry Andric   return S;
92981ad6265SDimitry Andric }
93081ad6265SDimitry Andric 
93181ad6265SDimitry Andric std::string RVVIntrinsic::getSuffixStr(
932bdd1243dSDimitry Andric     RVVTypeCache &TypeCache, BasicType Type, int Log2LMUL,
93381ad6265SDimitry Andric     llvm::ArrayRef<PrototypeDescriptor> PrototypeDescriptors) {
93481ad6265SDimitry Andric   SmallVector<std::string> SuffixStrs;
93581ad6265SDimitry Andric   for (auto PD : PrototypeDescriptors) {
936bdd1243dSDimitry Andric     auto T = TypeCache.computeType(Type, Log2LMUL, PD);
93781ad6265SDimitry Andric     SuffixStrs.push_back((*T)->getShortStr());
93881ad6265SDimitry Andric   }
93981ad6265SDimitry Andric   return join(SuffixStrs, "_");
94081ad6265SDimitry Andric }
94181ad6265SDimitry Andric 
942bdd1243dSDimitry Andric llvm::SmallVector<PrototypeDescriptor> RVVIntrinsic::computeBuiltinTypes(
943bdd1243dSDimitry Andric     llvm::ArrayRef<PrototypeDescriptor> Prototype, bool IsMasked,
944bdd1243dSDimitry Andric     bool HasMaskedOffOperand, bool HasVL, unsigned NF,
945*06c3fb27SDimitry Andric     PolicyScheme DefaultScheme, Policy PolicyAttrs, bool IsTuple) {
946972a253aSDimitry Andric   SmallVector<PrototypeDescriptor> NewPrototype(Prototype.begin(),
947972a253aSDimitry Andric                                                 Prototype.end());
948bdd1243dSDimitry Andric   bool HasPassthruOp = DefaultScheme == PolicyScheme::HasPassthruOperand;
949972a253aSDimitry Andric   if (IsMasked) {
950bdd1243dSDimitry Andric     // If HasMaskedOffOperand, insert result type as first input operand if
951bdd1243dSDimitry Andric     // need.
952bdd1243dSDimitry Andric     if (HasMaskedOffOperand && !PolicyAttrs.isTAMAPolicy()) {
953972a253aSDimitry Andric       if (NF == 1) {
954972a253aSDimitry Andric         NewPrototype.insert(NewPrototype.begin() + 1, NewPrototype[0]);
955bdd1243dSDimitry Andric       } else if (NF > 1) {
956*06c3fb27SDimitry Andric         if (IsTuple) {
957*06c3fb27SDimitry Andric           PrototypeDescriptor BasePtrOperand = Prototype[1];
958*06c3fb27SDimitry Andric           PrototypeDescriptor MaskoffType = PrototypeDescriptor(
959*06c3fb27SDimitry Andric               static_cast<uint8_t>(BaseTypeModifier::Vector),
960*06c3fb27SDimitry Andric               static_cast<uint8_t>(getTupleVTM(NF)),
961*06c3fb27SDimitry Andric               BasePtrOperand.TM & ~static_cast<uint8_t>(TypeModifier::Pointer));
962*06c3fb27SDimitry Andric           NewPrototype.insert(NewPrototype.begin() + 1, MaskoffType);
963*06c3fb27SDimitry Andric         } else {
964972a253aSDimitry Andric           // Convert
965972a253aSDimitry Andric           // (void, op0 address, op1 address, ...)
966972a253aSDimitry Andric           // to
967972a253aSDimitry Andric           // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
968972a253aSDimitry Andric           PrototypeDescriptor MaskoffType = NewPrototype[1];
969972a253aSDimitry Andric           MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer);
970bdd1243dSDimitry Andric           NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
971972a253aSDimitry Andric         }
972972a253aSDimitry Andric       }
973*06c3fb27SDimitry Andric     }
974972a253aSDimitry Andric     if (HasMaskedOffOperand && NF > 1) {
975972a253aSDimitry Andric       // Convert
976972a253aSDimitry Andric       // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
977972a253aSDimitry Andric       // to
978972a253aSDimitry Andric       // (void, op0 address, op1 address, ..., mask, maskedoff0, maskedoff1,
979972a253aSDimitry Andric       // ...)
980*06c3fb27SDimitry Andric       if (IsTuple)
981*06c3fb27SDimitry Andric         NewPrototype.insert(NewPrototype.begin() + 1,
982*06c3fb27SDimitry Andric                             PrototypeDescriptor::Mask);
983*06c3fb27SDimitry Andric       else
984972a253aSDimitry Andric         NewPrototype.insert(NewPrototype.begin() + NF + 1,
985972a253aSDimitry Andric                             PrototypeDescriptor::Mask);
986972a253aSDimitry Andric     } else {
987972a253aSDimitry Andric       // If IsMasked, insert PrototypeDescriptor:Mask as first input operand.
988972a253aSDimitry Andric       NewPrototype.insert(NewPrototype.begin() + 1, PrototypeDescriptor::Mask);
989972a253aSDimitry Andric     }
990bdd1243dSDimitry Andric   } else {
991bdd1243dSDimitry Andric     if (NF == 1) {
992bdd1243dSDimitry Andric       if (PolicyAttrs.isTUPolicy() && HasPassthruOp)
993bdd1243dSDimitry Andric         NewPrototype.insert(NewPrototype.begin(), NewPrototype[0]);
994bdd1243dSDimitry Andric     } else if (PolicyAttrs.isTUPolicy() && HasPassthruOp) {
995*06c3fb27SDimitry Andric       if (IsTuple) {
996*06c3fb27SDimitry Andric         PrototypeDescriptor BasePtrOperand = Prototype[0];
997*06c3fb27SDimitry Andric         PrototypeDescriptor MaskoffType = PrototypeDescriptor(
998*06c3fb27SDimitry Andric             static_cast<uint8_t>(BaseTypeModifier::Vector),
999*06c3fb27SDimitry Andric             static_cast<uint8_t>(getTupleVTM(NF)),
1000*06c3fb27SDimitry Andric             BasePtrOperand.TM & ~static_cast<uint8_t>(TypeModifier::Pointer));
1001*06c3fb27SDimitry Andric         NewPrototype.insert(NewPrototype.begin(), MaskoffType);
1002*06c3fb27SDimitry Andric       } else {
1003bdd1243dSDimitry Andric         // NF > 1 cases for segment load operations.
1004bdd1243dSDimitry Andric         // Convert
1005bdd1243dSDimitry Andric         // (void, op0 address, op1 address, ...)
1006bdd1243dSDimitry Andric         // to
1007bdd1243dSDimitry Andric         // (void, op0 address, op1 address, maskedoff0, maskedoff1, ...)
1008bdd1243dSDimitry Andric         PrototypeDescriptor MaskoffType = Prototype[1];
1009bdd1243dSDimitry Andric         MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer);
1010bdd1243dSDimitry Andric         NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1011bdd1243dSDimitry Andric       }
1012972a253aSDimitry Andric     }
1013*06c3fb27SDimitry Andric  }
1014972a253aSDimitry Andric 
1015972a253aSDimitry Andric   // If HasVL, append PrototypeDescriptor:VL to last operand
1016972a253aSDimitry Andric   if (HasVL)
1017972a253aSDimitry Andric     NewPrototype.push_back(PrototypeDescriptor::VL);
1018*06c3fb27SDimitry Andric 
1019972a253aSDimitry Andric   return NewPrototype;
1020972a253aSDimitry Andric }
1021972a253aSDimitry Andric 
10221ac55f4cSDimitry Andric llvm::SmallVector<Policy> RVVIntrinsic::getSupportedUnMaskedPolicies() {
10231ac55f4cSDimitry Andric   return {Policy(Policy::PolicyType::Undisturbed)}; // TU
1024bdd1243dSDimitry Andric }
1025bdd1243dSDimitry Andric 
1026bdd1243dSDimitry Andric llvm::SmallVector<Policy>
1027bdd1243dSDimitry Andric RVVIntrinsic::getSupportedMaskedPolicies(bool HasTailPolicy,
1028bdd1243dSDimitry Andric                                          bool HasMaskPolicy) {
1029bdd1243dSDimitry Andric   if (HasTailPolicy && HasMaskPolicy)
10301ac55f4cSDimitry Andric     return {Policy(Policy::PolicyType::Undisturbed,
10311ac55f4cSDimitry Andric                    Policy::PolicyType::Agnostic), // TUM
10321ac55f4cSDimitry Andric             Policy(Policy::PolicyType::Undisturbed,
10331ac55f4cSDimitry Andric                    Policy::PolicyType::Undisturbed), // TUMU
10341ac55f4cSDimitry Andric             Policy(Policy::PolicyType::Agnostic,
10351ac55f4cSDimitry Andric                    Policy::PolicyType::Undisturbed)}; // MU
1036bdd1243dSDimitry Andric   if (HasTailPolicy && !HasMaskPolicy)
1037bdd1243dSDimitry Andric     return {Policy(Policy::PolicyType::Undisturbed,
10381ac55f4cSDimitry Andric                    Policy::PolicyType::Agnostic)}; // TU
1039bdd1243dSDimitry Andric   if (!HasTailPolicy && HasMaskPolicy)
10401ac55f4cSDimitry Andric     return {Policy(Policy::PolicyType::Agnostic,
10411ac55f4cSDimitry Andric                    Policy::PolicyType::Undisturbed)}; // MU
1042bdd1243dSDimitry Andric   llvm_unreachable("An RVV instruction should not be without both tail policy "
1043bdd1243dSDimitry Andric                    "and mask policy");
1044bdd1243dSDimitry Andric }
1045bdd1243dSDimitry Andric 
1046*06c3fb27SDimitry Andric void RVVIntrinsic::updateNamesAndPolicy(
1047*06c3fb27SDimitry Andric     bool IsMasked, bool HasPolicy, std::string &Name, std::string &BuiltinName,
1048*06c3fb27SDimitry Andric     std::string &OverloadedName, Policy &PolicyAttrs, bool HasFRMRoundModeOp) {
1049bdd1243dSDimitry Andric 
1050bdd1243dSDimitry Andric   auto appendPolicySuffix = [&](const std::string &suffix) {
1051bdd1243dSDimitry Andric     Name += suffix;
1052bdd1243dSDimitry Andric     BuiltinName += suffix;
1053bdd1243dSDimitry Andric     OverloadedName += suffix;
1054bdd1243dSDimitry Andric   };
1055bdd1243dSDimitry Andric 
10561ac55f4cSDimitry Andric   // This follows the naming guideline under riscv-c-api-doc to add the
10571ac55f4cSDimitry Andric   // `__riscv_` suffix for all RVV intrinsics.
10581ac55f4cSDimitry Andric   Name = "__riscv_" + Name;
10591ac55f4cSDimitry Andric   OverloadedName = "__riscv_" + OverloadedName;
10601ac55f4cSDimitry Andric 
1061*06c3fb27SDimitry Andric   if (HasFRMRoundModeOp) {
1062*06c3fb27SDimitry Andric     Name += "_rm";
1063*06c3fb27SDimitry Andric     BuiltinName += "_rm";
1064*06c3fb27SDimitry Andric   }
1065*06c3fb27SDimitry Andric 
1066bdd1243dSDimitry Andric   if (IsMasked) {
10671ac55f4cSDimitry Andric     if (PolicyAttrs.isTUMUPolicy())
10681ac55f4cSDimitry Andric       appendPolicySuffix("_tumu");
10691ac55f4cSDimitry Andric     else if (PolicyAttrs.isTUMAPolicy())
10701ac55f4cSDimitry Andric       appendPolicySuffix("_tum");
10711ac55f4cSDimitry Andric     else if (PolicyAttrs.isTAMUPolicy())
10721ac55f4cSDimitry Andric       appendPolicySuffix("_mu");
10731ac55f4cSDimitry Andric     else if (PolicyAttrs.isTAMAPolicy()) {
1074bdd1243dSDimitry Andric       Name += "_m";
1075bdd1243dSDimitry Andric       BuiltinName += "_m";
10761ac55f4cSDimitry Andric     } else
1077bdd1243dSDimitry Andric       llvm_unreachable("Unhandled policy condition");
1078bdd1243dSDimitry Andric   } else {
1079bdd1243dSDimitry Andric     if (PolicyAttrs.isTUPolicy())
1080bdd1243dSDimitry Andric       appendPolicySuffix("_tu");
1081*06c3fb27SDimitry Andric     else if (PolicyAttrs.isTAPolicy()) // no suffix needed
1082*06c3fb27SDimitry Andric       return;
1083*06c3fb27SDimitry Andric     else
1084bdd1243dSDimitry Andric       llvm_unreachable("Unhandled policy condition");
1085bdd1243dSDimitry Andric   }
1086bdd1243dSDimitry Andric }
1087bdd1243dSDimitry Andric 
108881ad6265SDimitry Andric SmallVector<PrototypeDescriptor> parsePrototypes(StringRef Prototypes) {
108981ad6265SDimitry Andric   SmallVector<PrototypeDescriptor> PrototypeDescriptors;
109081ad6265SDimitry Andric   const StringRef Primaries("evwqom0ztul");
109181ad6265SDimitry Andric   while (!Prototypes.empty()) {
109281ad6265SDimitry Andric     size_t Idx = 0;
109381ad6265SDimitry Andric     // Skip over complex prototype because it could contain primitive type
109481ad6265SDimitry Andric     // character.
109581ad6265SDimitry Andric     if (Prototypes[0] == '(')
109681ad6265SDimitry Andric       Idx = Prototypes.find_first_of(')');
109781ad6265SDimitry Andric     Idx = Prototypes.find_first_of(Primaries, Idx);
109881ad6265SDimitry Andric     assert(Idx != StringRef::npos);
109981ad6265SDimitry Andric     auto PD = PrototypeDescriptor::parsePrototypeDescriptor(
110081ad6265SDimitry Andric         Prototypes.slice(0, Idx + 1));
110181ad6265SDimitry Andric     if (!PD)
110281ad6265SDimitry Andric       llvm_unreachable("Error during parsing prototype.");
110381ad6265SDimitry Andric     PrototypeDescriptors.push_back(*PD);
110481ad6265SDimitry Andric     Prototypes = Prototypes.drop_front(Idx + 1);
110581ad6265SDimitry Andric   }
110681ad6265SDimitry Andric   return PrototypeDescriptors;
110781ad6265SDimitry Andric }
110881ad6265SDimitry Andric 
1109972a253aSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const RVVIntrinsicRecord &Record) {
1110972a253aSDimitry Andric   OS << "{";
1111972a253aSDimitry Andric   OS << "\"" << Record.Name << "\",";
1112972a253aSDimitry Andric   if (Record.OverloadedName == nullptr ||
1113972a253aSDimitry Andric       StringRef(Record.OverloadedName).empty())
1114972a253aSDimitry Andric     OS << "nullptr,";
1115972a253aSDimitry Andric   else
1116972a253aSDimitry Andric     OS << "\"" << Record.OverloadedName << "\",";
1117972a253aSDimitry Andric   OS << Record.PrototypeIndex << ",";
1118972a253aSDimitry Andric   OS << Record.SuffixIndex << ",";
1119972a253aSDimitry Andric   OS << Record.OverloadedSuffixIndex << ",";
1120972a253aSDimitry Andric   OS << (int)Record.PrototypeLength << ",";
1121972a253aSDimitry Andric   OS << (int)Record.SuffixLength << ",";
1122972a253aSDimitry Andric   OS << (int)Record.OverloadedSuffixSize << ",";
1123972a253aSDimitry Andric   OS << (int)Record.RequiredExtensions << ",";
1124972a253aSDimitry Andric   OS << (int)Record.TypeRangeMask << ",";
1125972a253aSDimitry Andric   OS << (int)Record.Log2LMULMask << ",";
1126972a253aSDimitry Andric   OS << (int)Record.NF << ",";
1127972a253aSDimitry Andric   OS << (int)Record.HasMasked << ",";
1128972a253aSDimitry Andric   OS << (int)Record.HasVL << ",";
1129972a253aSDimitry Andric   OS << (int)Record.HasMaskedOffOperand << ",";
1130bdd1243dSDimitry Andric   OS << (int)Record.HasTailPolicy << ",";
1131bdd1243dSDimitry Andric   OS << (int)Record.HasMaskPolicy << ",";
1132*06c3fb27SDimitry Andric   OS << (int)Record.HasFRMRoundModeOp << ",";
1133*06c3fb27SDimitry Andric   OS << (int)Record.IsTuple << ",";
1134bdd1243dSDimitry Andric   OS << (int)Record.UnMaskedPolicyScheme << ",";
1135bdd1243dSDimitry Andric   OS << (int)Record.MaskedPolicyScheme << ",";
1136972a253aSDimitry Andric   OS << "},\n";
1137972a253aSDimitry Andric   return OS;
1138972a253aSDimitry Andric }
1139972a253aSDimitry Andric 
114081ad6265SDimitry Andric } // end namespace RISCV
114181ad6265SDimitry Andric } // end namespace clang
1142