xref: /freebsd/contrib/llvm-project/clang/lib/Support/RISCVVIntrinsicUtils.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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/StringSet.h"
1481ad6265SDimitry Andric #include "llvm/ADT/Twine.h"
15bdd1243dSDimitry Andric #include "llvm/Support/ErrorHandling.h"
1681ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h"
1781ad6265SDimitry Andric #include <numeric>
18bdd1243dSDimitry Andric #include <optional>
1981ad6265SDimitry Andric 
2081ad6265SDimitry Andric using namespace llvm;
2181ad6265SDimitry Andric 
2281ad6265SDimitry Andric namespace clang {
2381ad6265SDimitry Andric namespace RISCV {
2481ad6265SDimitry Andric 
2581ad6265SDimitry Andric const PrototypeDescriptor PrototypeDescriptor::Mask = PrototypeDescriptor(
2681ad6265SDimitry Andric     BaseTypeModifier::Vector, VectorTypeModifier::MaskVector);
2781ad6265SDimitry Andric const PrototypeDescriptor PrototypeDescriptor::VL =
2881ad6265SDimitry Andric     PrototypeDescriptor(BaseTypeModifier::SizeT);
2981ad6265SDimitry Andric const PrototypeDescriptor PrototypeDescriptor::Vector =
3081ad6265SDimitry Andric     PrototypeDescriptor(BaseTypeModifier::Vector);
3181ad6265SDimitry Andric 
3281ad6265SDimitry Andric //===----------------------------------------------------------------------===//
3381ad6265SDimitry Andric // Type implementation
3481ad6265SDimitry Andric //===----------------------------------------------------------------------===//
3581ad6265SDimitry Andric 
LMULType(int NewLog2LMUL)3681ad6265SDimitry Andric LMULType::LMULType(int NewLog2LMUL) {
3781ad6265SDimitry Andric   // Check Log2LMUL is -3, -2, -1, 0, 1, 2, 3
3881ad6265SDimitry Andric   assert(NewLog2LMUL <= 3 && NewLog2LMUL >= -3 && "Bad LMUL number!");
3981ad6265SDimitry Andric   Log2LMUL = NewLog2LMUL;
4081ad6265SDimitry Andric }
4181ad6265SDimitry Andric 
str() const4281ad6265SDimitry Andric std::string LMULType::str() const {
4381ad6265SDimitry Andric   if (Log2LMUL < 0)
4481ad6265SDimitry Andric     return "mf" + utostr(1ULL << (-Log2LMUL));
4581ad6265SDimitry Andric   return "m" + utostr(1ULL << Log2LMUL);
4681ad6265SDimitry Andric }
4781ad6265SDimitry Andric 
getScale(unsigned ElementBitwidth) const4881ad6265SDimitry Andric VScaleVal LMULType::getScale(unsigned ElementBitwidth) const {
4981ad6265SDimitry Andric   int Log2ScaleResult = 0;
5081ad6265SDimitry Andric   switch (ElementBitwidth) {
5181ad6265SDimitry Andric   default:
5281ad6265SDimitry Andric     break;
5381ad6265SDimitry Andric   case 8:
5481ad6265SDimitry Andric     Log2ScaleResult = Log2LMUL + 3;
5581ad6265SDimitry Andric     break;
5681ad6265SDimitry Andric   case 16:
5781ad6265SDimitry Andric     Log2ScaleResult = Log2LMUL + 2;
5881ad6265SDimitry Andric     break;
5981ad6265SDimitry Andric   case 32:
6081ad6265SDimitry Andric     Log2ScaleResult = Log2LMUL + 1;
6181ad6265SDimitry Andric     break;
6281ad6265SDimitry Andric   case 64:
6381ad6265SDimitry Andric     Log2ScaleResult = Log2LMUL;
6481ad6265SDimitry Andric     break;
6581ad6265SDimitry Andric   }
6681ad6265SDimitry Andric   // Illegal vscale result would be less than 1
6781ad6265SDimitry Andric   if (Log2ScaleResult < 0)
68bdd1243dSDimitry Andric     return std::nullopt;
6981ad6265SDimitry Andric   return 1 << Log2ScaleResult;
7081ad6265SDimitry Andric }
7181ad6265SDimitry Andric 
MulLog2LMUL(int log2LMUL)7281ad6265SDimitry Andric void LMULType::MulLog2LMUL(int log2LMUL) { Log2LMUL += log2LMUL; }
7381ad6265SDimitry Andric 
RVVType(BasicType BT,int Log2LMUL,const PrototypeDescriptor & prototype)7481ad6265SDimitry Andric RVVType::RVVType(BasicType BT, int Log2LMUL,
7581ad6265SDimitry Andric                  const PrototypeDescriptor &prototype)
7681ad6265SDimitry Andric     : BT(BT), LMUL(LMULType(Log2LMUL)) {
7781ad6265SDimitry Andric   applyBasicType();
7881ad6265SDimitry Andric   applyModifier(prototype);
7981ad6265SDimitry Andric   Valid = verifyType();
8081ad6265SDimitry Andric   if (Valid) {
8181ad6265SDimitry Andric     initBuiltinStr();
8281ad6265SDimitry Andric     initTypeStr();
8381ad6265SDimitry Andric     if (isVector()) {
8481ad6265SDimitry Andric       initClangBuiltinStr();
8581ad6265SDimitry Andric     }
8681ad6265SDimitry Andric   }
8781ad6265SDimitry Andric }
8881ad6265SDimitry Andric 
8981ad6265SDimitry Andric // clang-format off
9081ad6265SDimitry Andric // boolean type are encoded the ratio of n (SEW/LMUL)
9181ad6265SDimitry Andric // SEW/LMUL | 1         | 2         | 4         | 8        | 16        | 32        | 64
9281ad6265SDimitry Andric // c type   | vbool64_t | vbool32_t | vbool16_t | vbool8_t | vbool4_t  | vbool2_t  | vbool1_t
9381ad6265SDimitry Andric // IR type  | nxv1i1    | nxv2i1    | nxv4i1    | nxv8i1   | nxv16i1   | nxv32i1   | nxv64i1
9481ad6265SDimitry Andric 
9581ad6265SDimitry Andric // type\lmul | 1/8    | 1/4      | 1/2     | 1       | 2        | 4        | 8
9681ad6265SDimitry Andric // --------  |------  | -------- | ------- | ------- | -------- | -------- | --------
9781ad6265SDimitry Andric // i64       | N/A    | N/A      | N/A     | nxv1i64 | nxv2i64  | nxv4i64  | nxv8i64
9881ad6265SDimitry Andric // i32       | N/A    | N/A      | nxv1i32 | nxv2i32 | nxv4i32  | nxv8i32  | nxv16i32
9981ad6265SDimitry Andric // i16       | N/A    | nxv1i16  | nxv2i16 | nxv4i16 | nxv8i16  | nxv16i16 | nxv32i16
10081ad6265SDimitry Andric // i8        | nxv1i8 | nxv2i8   | nxv4i8  | nxv8i8  | nxv16i8  | nxv32i8  | nxv64i8
10181ad6265SDimitry Andric // double    | N/A    | N/A      | N/A     | nxv1f64 | nxv2f64  | nxv4f64  | nxv8f64
10281ad6265SDimitry Andric // float     | N/A    | N/A      | nxv1f32 | nxv2f32 | nxv4f32  | nxv8f32  | nxv16f32
10381ad6265SDimitry Andric // half      | N/A    | nxv1f16  | nxv2f16 | nxv4f16 | nxv8f16  | nxv16f16 | nxv32f16
1045f757f3fSDimitry Andric // bfloat16  | N/A    | nxv1bf16 | nxv2bf16| nxv4bf16| nxv8bf16 | nxv16bf16| nxv32bf16
10581ad6265SDimitry Andric // clang-format on
10681ad6265SDimitry Andric 
verifyType() const10781ad6265SDimitry 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;
1165f757f3fSDimitry Andric   if (isBFloat() && ElementBitwidth != 16)
1175f757f3fSDimitry Andric     return false;
11806c3fb27SDimitry Andric   if (IsTuple && (NF == 1 || NF > 8))
11906c3fb27SDimitry Andric     return false;
12006c3fb27SDimitry Andric   if (IsTuple && (1 << std::max(0, LMUL.Log2LMUL)) * NF > 8)
12106c3fb27SDimitry Andric     return false;
122bdd1243dSDimitry Andric   unsigned V = *Scale;
12381ad6265SDimitry Andric   switch (ElementBitwidth) {
12481ad6265SDimitry Andric   case 1:
12581ad6265SDimitry Andric   case 8:
12681ad6265SDimitry Andric     // Check Scale is 1,2,4,8,16,32,64
12781ad6265SDimitry Andric     return (V <= 64 && isPowerOf2_32(V));
12881ad6265SDimitry Andric   case 16:
12981ad6265SDimitry Andric     // Check Scale is 1,2,4,8,16,32
13081ad6265SDimitry Andric     return (V <= 32 && isPowerOf2_32(V));
13181ad6265SDimitry Andric   case 32:
13281ad6265SDimitry Andric     // Check Scale is 1,2,4,8,16
13381ad6265SDimitry Andric     return (V <= 16 && isPowerOf2_32(V));
13481ad6265SDimitry Andric   case 64:
13581ad6265SDimitry Andric     // Check Scale is 1,2,4,8
13681ad6265SDimitry Andric     return (V <= 8 && isPowerOf2_32(V));
13781ad6265SDimitry Andric   }
13881ad6265SDimitry Andric   return false;
13981ad6265SDimitry Andric }
14081ad6265SDimitry Andric 
initBuiltinStr()14181ad6265SDimitry Andric void RVVType::initBuiltinStr() {
14281ad6265SDimitry Andric   assert(isValid() && "RVVType is invalid");
14381ad6265SDimitry Andric   switch (ScalarType) {
14481ad6265SDimitry Andric   case ScalarTypeKind::Void:
14581ad6265SDimitry Andric     BuiltinStr = "v";
14681ad6265SDimitry Andric     return;
14781ad6265SDimitry Andric   case ScalarTypeKind::Size_t:
14881ad6265SDimitry Andric     BuiltinStr = "z";
14981ad6265SDimitry Andric     if (IsImmediate)
15081ad6265SDimitry Andric       BuiltinStr = "I" + BuiltinStr;
15181ad6265SDimitry Andric     if (IsPointer)
15281ad6265SDimitry Andric       BuiltinStr += "*";
15381ad6265SDimitry Andric     return;
15481ad6265SDimitry Andric   case ScalarTypeKind::Ptrdiff_t:
15581ad6265SDimitry Andric     BuiltinStr = "Y";
15681ad6265SDimitry Andric     return;
15781ad6265SDimitry Andric   case ScalarTypeKind::UnsignedLong:
15881ad6265SDimitry Andric     BuiltinStr = "ULi";
15981ad6265SDimitry Andric     return;
16081ad6265SDimitry Andric   case ScalarTypeKind::SignedLong:
16181ad6265SDimitry Andric     BuiltinStr = "Li";
16281ad6265SDimitry Andric     return;
16381ad6265SDimitry Andric   case ScalarTypeKind::Boolean:
16481ad6265SDimitry Andric     assert(ElementBitwidth == 1);
16581ad6265SDimitry Andric     BuiltinStr += "b";
16681ad6265SDimitry Andric     break;
16781ad6265SDimitry Andric   case ScalarTypeKind::SignedInteger:
16881ad6265SDimitry Andric   case ScalarTypeKind::UnsignedInteger:
16981ad6265SDimitry Andric     switch (ElementBitwidth) {
17081ad6265SDimitry Andric     case 8:
17181ad6265SDimitry Andric       BuiltinStr += "c";
17281ad6265SDimitry Andric       break;
17381ad6265SDimitry Andric     case 16:
17481ad6265SDimitry Andric       BuiltinStr += "s";
17581ad6265SDimitry Andric       break;
17681ad6265SDimitry Andric     case 32:
17781ad6265SDimitry Andric       BuiltinStr += "i";
17881ad6265SDimitry Andric       break;
17981ad6265SDimitry Andric     case 64:
18081ad6265SDimitry Andric       BuiltinStr += "Wi";
18181ad6265SDimitry Andric       break;
18281ad6265SDimitry Andric     default:
18381ad6265SDimitry Andric       llvm_unreachable("Unhandled ElementBitwidth!");
18481ad6265SDimitry Andric     }
18581ad6265SDimitry Andric     if (isSignedInteger())
18681ad6265SDimitry Andric       BuiltinStr = "S" + BuiltinStr;
18781ad6265SDimitry Andric     else
18881ad6265SDimitry Andric       BuiltinStr = "U" + BuiltinStr;
18981ad6265SDimitry Andric     break;
19081ad6265SDimitry Andric   case ScalarTypeKind::Float:
19181ad6265SDimitry Andric     switch (ElementBitwidth) {
19281ad6265SDimitry Andric     case 16:
19381ad6265SDimitry Andric       BuiltinStr += "x";
19481ad6265SDimitry Andric       break;
19581ad6265SDimitry Andric     case 32:
19681ad6265SDimitry Andric       BuiltinStr += "f";
19781ad6265SDimitry Andric       break;
19881ad6265SDimitry Andric     case 64:
19981ad6265SDimitry Andric       BuiltinStr += "d";
20081ad6265SDimitry Andric       break;
20181ad6265SDimitry Andric     default:
20281ad6265SDimitry Andric       llvm_unreachable("Unhandled ElementBitwidth!");
20381ad6265SDimitry Andric     }
20481ad6265SDimitry Andric     break;
2055f757f3fSDimitry Andric   case ScalarTypeKind::BFloat:
206647cbc5dSDimitry Andric     BuiltinStr += "y";
2075f757f3fSDimitry Andric     break;
20881ad6265SDimitry Andric   default:
20981ad6265SDimitry Andric     llvm_unreachable("ScalarType is invalid!");
21081ad6265SDimitry Andric   }
21181ad6265SDimitry Andric   if (IsImmediate)
21281ad6265SDimitry Andric     BuiltinStr = "I" + BuiltinStr;
21381ad6265SDimitry Andric   if (isScalar()) {
21481ad6265SDimitry Andric     if (IsConstant)
21581ad6265SDimitry Andric       BuiltinStr += "C";
21681ad6265SDimitry Andric     if (IsPointer)
21781ad6265SDimitry Andric       BuiltinStr += "*";
21881ad6265SDimitry Andric     return;
21981ad6265SDimitry Andric   }
22081ad6265SDimitry Andric   BuiltinStr = "q" + utostr(*Scale) + BuiltinStr;
22181ad6265SDimitry Andric   // Pointer to vector types. Defined for segment load intrinsics.
22281ad6265SDimitry Andric   // segment load intrinsics have pointer type arguments to store the loaded
22381ad6265SDimitry Andric   // vector values.
22481ad6265SDimitry Andric   if (IsPointer)
22581ad6265SDimitry Andric     BuiltinStr += "*";
22606c3fb27SDimitry Andric 
22706c3fb27SDimitry Andric   if (IsTuple)
22806c3fb27SDimitry Andric     BuiltinStr = "T" + utostr(NF) + BuiltinStr;
22981ad6265SDimitry Andric }
23081ad6265SDimitry Andric 
initClangBuiltinStr()23181ad6265SDimitry Andric void RVVType::initClangBuiltinStr() {
23281ad6265SDimitry Andric   assert(isValid() && "RVVType is invalid");
23381ad6265SDimitry Andric   assert(isVector() && "Handle Vector type only");
23481ad6265SDimitry Andric 
23581ad6265SDimitry Andric   ClangBuiltinStr = "__rvv_";
23681ad6265SDimitry Andric   switch (ScalarType) {
23781ad6265SDimitry Andric   case ScalarTypeKind::Boolean:
23881ad6265SDimitry Andric     ClangBuiltinStr += "bool" + utostr(64 / *Scale) + "_t";
23981ad6265SDimitry Andric     return;
24081ad6265SDimitry Andric   case ScalarTypeKind::Float:
24181ad6265SDimitry Andric     ClangBuiltinStr += "float";
24281ad6265SDimitry Andric     break;
2435f757f3fSDimitry Andric   case ScalarTypeKind::BFloat:
2445f757f3fSDimitry Andric     ClangBuiltinStr += "bfloat";
2455f757f3fSDimitry Andric     break;
24681ad6265SDimitry Andric   case ScalarTypeKind::SignedInteger:
24781ad6265SDimitry Andric     ClangBuiltinStr += "int";
24881ad6265SDimitry Andric     break;
24981ad6265SDimitry Andric   case ScalarTypeKind::UnsignedInteger:
25081ad6265SDimitry Andric     ClangBuiltinStr += "uint";
25181ad6265SDimitry Andric     break;
25281ad6265SDimitry Andric   default:
25381ad6265SDimitry Andric     llvm_unreachable("ScalarTypeKind is invalid");
25481ad6265SDimitry Andric   }
25506c3fb27SDimitry Andric   ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.str() +
25606c3fb27SDimitry Andric                      (IsTuple ? "x" + utostr(NF) : "") + "_t";
25781ad6265SDimitry Andric }
25881ad6265SDimitry Andric 
initTypeStr()25981ad6265SDimitry Andric void RVVType::initTypeStr() {
26081ad6265SDimitry Andric   assert(isValid() && "RVVType is invalid");
26181ad6265SDimitry Andric 
26281ad6265SDimitry Andric   if (IsConstant)
26381ad6265SDimitry Andric     Str += "const ";
26481ad6265SDimitry Andric 
26581ad6265SDimitry Andric   auto getTypeString = [&](StringRef TypeStr) {
26681ad6265SDimitry Andric     if (isScalar())
26781ad6265SDimitry Andric       return Twine(TypeStr + Twine(ElementBitwidth) + "_t").str();
26806c3fb27SDimitry Andric     return Twine("v" + TypeStr + Twine(ElementBitwidth) + LMUL.str() +
26906c3fb27SDimitry Andric                  (IsTuple ? "x" + utostr(NF) : "") + "_t")
27081ad6265SDimitry Andric         .str();
27181ad6265SDimitry Andric   };
27281ad6265SDimitry Andric 
27381ad6265SDimitry Andric   switch (ScalarType) {
27481ad6265SDimitry Andric   case ScalarTypeKind::Void:
27581ad6265SDimitry Andric     Str = "void";
27681ad6265SDimitry Andric     return;
27781ad6265SDimitry Andric   case ScalarTypeKind::Size_t:
27881ad6265SDimitry Andric     Str = "size_t";
27981ad6265SDimitry Andric     if (IsPointer)
28081ad6265SDimitry Andric       Str += " *";
28181ad6265SDimitry Andric     return;
28281ad6265SDimitry Andric   case ScalarTypeKind::Ptrdiff_t:
28381ad6265SDimitry Andric     Str = "ptrdiff_t";
28481ad6265SDimitry Andric     return;
28581ad6265SDimitry Andric   case ScalarTypeKind::UnsignedLong:
28681ad6265SDimitry Andric     Str = "unsigned long";
28781ad6265SDimitry Andric     return;
28881ad6265SDimitry Andric   case ScalarTypeKind::SignedLong:
28981ad6265SDimitry Andric     Str = "long";
29081ad6265SDimitry Andric     return;
29181ad6265SDimitry Andric   case ScalarTypeKind::Boolean:
29281ad6265SDimitry Andric     if (isScalar())
29381ad6265SDimitry Andric       Str += "bool";
29481ad6265SDimitry Andric     else
29581ad6265SDimitry Andric       // Vector bool is special case, the formulate is
29681ad6265SDimitry Andric       // `vbool<N>_t = MVT::nxv<64/N>i1` ex. vbool16_t = MVT::4i1
29781ad6265SDimitry Andric       Str += "vbool" + utostr(64 / *Scale) + "_t";
29881ad6265SDimitry Andric     break;
29981ad6265SDimitry Andric   case ScalarTypeKind::Float:
30081ad6265SDimitry Andric     if (isScalar()) {
30181ad6265SDimitry Andric       if (ElementBitwidth == 64)
30281ad6265SDimitry Andric         Str += "double";
30381ad6265SDimitry Andric       else if (ElementBitwidth == 32)
30481ad6265SDimitry Andric         Str += "float";
30581ad6265SDimitry Andric       else if (ElementBitwidth == 16)
30681ad6265SDimitry Andric         Str += "_Float16";
30781ad6265SDimitry Andric       else
30881ad6265SDimitry Andric         llvm_unreachable("Unhandled floating type.");
30981ad6265SDimitry Andric     } else
31081ad6265SDimitry Andric       Str += getTypeString("float");
31181ad6265SDimitry Andric     break;
3125f757f3fSDimitry Andric   case ScalarTypeKind::BFloat:
3135f757f3fSDimitry Andric     if (isScalar()) {
3145f757f3fSDimitry Andric       if (ElementBitwidth == 16)
3155f757f3fSDimitry Andric         Str += "__bf16";
3165f757f3fSDimitry Andric       else
3175f757f3fSDimitry Andric         llvm_unreachable("Unhandled floating type.");
3185f757f3fSDimitry Andric     } else
3195f757f3fSDimitry Andric       Str += getTypeString("bfloat");
3205f757f3fSDimitry Andric     break;
32181ad6265SDimitry Andric   case ScalarTypeKind::SignedInteger:
32281ad6265SDimitry Andric     Str += getTypeString("int");
32381ad6265SDimitry Andric     break;
32481ad6265SDimitry Andric   case ScalarTypeKind::UnsignedInteger:
32581ad6265SDimitry Andric     Str += getTypeString("uint");
32681ad6265SDimitry Andric     break;
32781ad6265SDimitry Andric   default:
32881ad6265SDimitry Andric     llvm_unreachable("ScalarType is invalid!");
32981ad6265SDimitry Andric   }
33081ad6265SDimitry Andric   if (IsPointer)
33181ad6265SDimitry Andric     Str += " *";
33281ad6265SDimitry Andric }
33381ad6265SDimitry Andric 
initShortStr()33481ad6265SDimitry Andric void RVVType::initShortStr() {
33581ad6265SDimitry Andric   switch (ScalarType) {
33681ad6265SDimitry Andric   case ScalarTypeKind::Boolean:
33781ad6265SDimitry Andric     assert(isVector());
33881ad6265SDimitry Andric     ShortStr = "b" + utostr(64 / *Scale);
33981ad6265SDimitry Andric     return;
34081ad6265SDimitry Andric   case ScalarTypeKind::Float:
34181ad6265SDimitry Andric     ShortStr = "f" + utostr(ElementBitwidth);
34281ad6265SDimitry Andric     break;
3435f757f3fSDimitry Andric   case ScalarTypeKind::BFloat:
3445f757f3fSDimitry Andric     ShortStr = "bf" + utostr(ElementBitwidth);
3455f757f3fSDimitry Andric     break;
34681ad6265SDimitry Andric   case ScalarTypeKind::SignedInteger:
34781ad6265SDimitry Andric     ShortStr = "i" + utostr(ElementBitwidth);
34881ad6265SDimitry Andric     break;
34981ad6265SDimitry Andric   case ScalarTypeKind::UnsignedInteger:
35081ad6265SDimitry Andric     ShortStr = "u" + utostr(ElementBitwidth);
35181ad6265SDimitry Andric     break;
35281ad6265SDimitry Andric   default:
35381ad6265SDimitry Andric     llvm_unreachable("Unhandled case!");
35481ad6265SDimitry Andric   }
35581ad6265SDimitry Andric   if (isVector())
35681ad6265SDimitry Andric     ShortStr += LMUL.str();
35706c3fb27SDimitry Andric   if (isTuple())
35806c3fb27SDimitry Andric     ShortStr += "x" + utostr(NF);
35906c3fb27SDimitry Andric }
36006c3fb27SDimitry Andric 
getTupleVTM(unsigned NF)36106c3fb27SDimitry Andric static VectorTypeModifier getTupleVTM(unsigned NF) {
36206c3fb27SDimitry Andric   assert(2 <= NF && NF <= 8 && "2 <= NF <= 8");
36306c3fb27SDimitry Andric   return static_cast<VectorTypeModifier>(
36406c3fb27SDimitry Andric       static_cast<uint8_t>(VectorTypeModifier::Tuple2) + (NF - 2));
36581ad6265SDimitry Andric }
36681ad6265SDimitry Andric 
applyBasicType()36781ad6265SDimitry Andric void RVVType::applyBasicType() {
36881ad6265SDimitry Andric   switch (BT) {
36981ad6265SDimitry Andric   case BasicType::Int8:
37081ad6265SDimitry Andric     ElementBitwidth = 8;
37181ad6265SDimitry Andric     ScalarType = ScalarTypeKind::SignedInteger;
37281ad6265SDimitry Andric     break;
37381ad6265SDimitry Andric   case BasicType::Int16:
37481ad6265SDimitry Andric     ElementBitwidth = 16;
37581ad6265SDimitry Andric     ScalarType = ScalarTypeKind::SignedInteger;
37681ad6265SDimitry Andric     break;
37781ad6265SDimitry Andric   case BasicType::Int32:
37881ad6265SDimitry Andric     ElementBitwidth = 32;
37981ad6265SDimitry Andric     ScalarType = ScalarTypeKind::SignedInteger;
38081ad6265SDimitry Andric     break;
38181ad6265SDimitry Andric   case BasicType::Int64:
38281ad6265SDimitry Andric     ElementBitwidth = 64;
38381ad6265SDimitry Andric     ScalarType = ScalarTypeKind::SignedInteger;
38481ad6265SDimitry Andric     break;
38581ad6265SDimitry Andric   case BasicType::Float16:
38681ad6265SDimitry Andric     ElementBitwidth = 16;
38781ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Float;
38881ad6265SDimitry Andric     break;
38981ad6265SDimitry Andric   case BasicType::Float32:
39081ad6265SDimitry Andric     ElementBitwidth = 32;
39181ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Float;
39281ad6265SDimitry Andric     break;
39381ad6265SDimitry Andric   case BasicType::Float64:
39481ad6265SDimitry Andric     ElementBitwidth = 64;
39581ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Float;
39681ad6265SDimitry Andric     break;
3975f757f3fSDimitry Andric   case BasicType::BFloat16:
3985f757f3fSDimitry Andric     ElementBitwidth = 16;
3995f757f3fSDimitry Andric     ScalarType = ScalarTypeKind::BFloat;
4005f757f3fSDimitry Andric     break;
40181ad6265SDimitry Andric   default:
40281ad6265SDimitry Andric     llvm_unreachable("Unhandled type code!");
40381ad6265SDimitry Andric   }
40481ad6265SDimitry Andric   assert(ElementBitwidth != 0 && "Bad element bitwidth!");
40581ad6265SDimitry Andric }
40681ad6265SDimitry Andric 
407bdd1243dSDimitry Andric std::optional<PrototypeDescriptor>
parsePrototypeDescriptor(llvm::StringRef PrototypeDescriptorStr)408bdd1243dSDimitry Andric PrototypeDescriptor::parsePrototypeDescriptor(
40981ad6265SDimitry Andric     llvm::StringRef PrototypeDescriptorStr) {
41081ad6265SDimitry Andric   PrototypeDescriptor PD;
41181ad6265SDimitry Andric   BaseTypeModifier PT = BaseTypeModifier::Invalid;
41281ad6265SDimitry Andric   VectorTypeModifier VTM = VectorTypeModifier::NoModifier;
41381ad6265SDimitry Andric 
41481ad6265SDimitry Andric   if (PrototypeDescriptorStr.empty())
41581ad6265SDimitry Andric     return PD;
41681ad6265SDimitry Andric 
41781ad6265SDimitry Andric   // Handle base type modifier
41881ad6265SDimitry Andric   auto PType = PrototypeDescriptorStr.back();
41981ad6265SDimitry Andric   switch (PType) {
42081ad6265SDimitry Andric   case 'e':
42181ad6265SDimitry Andric     PT = BaseTypeModifier::Scalar;
42281ad6265SDimitry Andric     break;
42381ad6265SDimitry Andric   case 'v':
42481ad6265SDimitry Andric     PT = BaseTypeModifier::Vector;
42581ad6265SDimitry Andric     break;
42681ad6265SDimitry Andric   case 'w':
42781ad6265SDimitry Andric     PT = BaseTypeModifier::Vector;
42881ad6265SDimitry Andric     VTM = VectorTypeModifier::Widening2XVector;
42981ad6265SDimitry Andric     break;
43081ad6265SDimitry Andric   case 'q':
43181ad6265SDimitry Andric     PT = BaseTypeModifier::Vector;
43281ad6265SDimitry Andric     VTM = VectorTypeModifier::Widening4XVector;
43381ad6265SDimitry Andric     break;
43481ad6265SDimitry Andric   case 'o':
43581ad6265SDimitry Andric     PT = BaseTypeModifier::Vector;
43681ad6265SDimitry Andric     VTM = VectorTypeModifier::Widening8XVector;
43781ad6265SDimitry Andric     break;
43881ad6265SDimitry Andric   case 'm':
43981ad6265SDimitry Andric     PT = BaseTypeModifier::Vector;
44081ad6265SDimitry Andric     VTM = VectorTypeModifier::MaskVector;
44181ad6265SDimitry Andric     break;
44281ad6265SDimitry Andric   case '0':
44381ad6265SDimitry Andric     PT = BaseTypeModifier::Void;
44481ad6265SDimitry Andric     break;
44581ad6265SDimitry Andric   case 'z':
44681ad6265SDimitry Andric     PT = BaseTypeModifier::SizeT;
44781ad6265SDimitry Andric     break;
44881ad6265SDimitry Andric   case 't':
44981ad6265SDimitry Andric     PT = BaseTypeModifier::Ptrdiff;
45081ad6265SDimitry Andric     break;
45181ad6265SDimitry Andric   case 'u':
45281ad6265SDimitry Andric     PT = BaseTypeModifier::UnsignedLong;
45381ad6265SDimitry Andric     break;
45481ad6265SDimitry Andric   case 'l':
45581ad6265SDimitry Andric     PT = BaseTypeModifier::SignedLong;
45681ad6265SDimitry Andric     break;
4575f757f3fSDimitry Andric   case 'f':
4585f757f3fSDimitry Andric     PT = BaseTypeModifier::Float32;
4595f757f3fSDimitry Andric     break;
46081ad6265SDimitry Andric   default:
46181ad6265SDimitry Andric     llvm_unreachable("Illegal primitive type transformers!");
46281ad6265SDimitry Andric   }
46381ad6265SDimitry Andric   PD.PT = static_cast<uint8_t>(PT);
46481ad6265SDimitry Andric   PrototypeDescriptorStr = PrototypeDescriptorStr.drop_back();
46581ad6265SDimitry Andric 
46681ad6265SDimitry Andric   // Compute the vector type transformers, it can only appear one time.
4675f757f3fSDimitry Andric   if (PrototypeDescriptorStr.starts_with("(")) {
46881ad6265SDimitry Andric     assert(VTM == VectorTypeModifier::NoModifier &&
46981ad6265SDimitry Andric            "VectorTypeModifier should only have one modifier");
47081ad6265SDimitry Andric     size_t Idx = PrototypeDescriptorStr.find(')');
47181ad6265SDimitry Andric     assert(Idx != StringRef::npos);
47281ad6265SDimitry Andric     StringRef ComplexType = PrototypeDescriptorStr.slice(1, Idx);
47381ad6265SDimitry Andric     PrototypeDescriptorStr = PrototypeDescriptorStr.drop_front(Idx + 1);
47481ad6265SDimitry Andric     assert(!PrototypeDescriptorStr.contains('(') &&
47581ad6265SDimitry Andric            "Only allow one vector type modifier");
47681ad6265SDimitry Andric 
47781ad6265SDimitry Andric     auto ComplexTT = ComplexType.split(":");
47881ad6265SDimitry Andric     if (ComplexTT.first == "Log2EEW") {
47981ad6265SDimitry Andric       uint32_t Log2EEW;
48081ad6265SDimitry Andric       if (ComplexTT.second.getAsInteger(10, Log2EEW)) {
48181ad6265SDimitry Andric         llvm_unreachable("Invalid Log2EEW value!");
482bdd1243dSDimitry Andric         return std::nullopt;
48381ad6265SDimitry Andric       }
48481ad6265SDimitry Andric       switch (Log2EEW) {
48581ad6265SDimitry Andric       case 3:
48681ad6265SDimitry Andric         VTM = VectorTypeModifier::Log2EEW3;
48781ad6265SDimitry Andric         break;
48881ad6265SDimitry Andric       case 4:
48981ad6265SDimitry Andric         VTM = VectorTypeModifier::Log2EEW4;
49081ad6265SDimitry Andric         break;
49181ad6265SDimitry Andric       case 5:
49281ad6265SDimitry Andric         VTM = VectorTypeModifier::Log2EEW5;
49381ad6265SDimitry Andric         break;
49481ad6265SDimitry Andric       case 6:
49581ad6265SDimitry Andric         VTM = VectorTypeModifier::Log2EEW6;
49681ad6265SDimitry Andric         break;
49781ad6265SDimitry Andric       default:
49881ad6265SDimitry Andric         llvm_unreachable("Invalid Log2EEW value, should be [3-6]");
499bdd1243dSDimitry Andric         return std::nullopt;
50081ad6265SDimitry Andric       }
50181ad6265SDimitry Andric     } else if (ComplexTT.first == "FixedSEW") {
50281ad6265SDimitry Andric       uint32_t NewSEW;
50381ad6265SDimitry Andric       if (ComplexTT.second.getAsInteger(10, NewSEW)) {
50481ad6265SDimitry Andric         llvm_unreachable("Invalid FixedSEW value!");
505bdd1243dSDimitry Andric         return std::nullopt;
50681ad6265SDimitry Andric       }
50781ad6265SDimitry Andric       switch (NewSEW) {
50881ad6265SDimitry Andric       case 8:
50981ad6265SDimitry Andric         VTM = VectorTypeModifier::FixedSEW8;
51081ad6265SDimitry Andric         break;
51181ad6265SDimitry Andric       case 16:
51281ad6265SDimitry Andric         VTM = VectorTypeModifier::FixedSEW16;
51381ad6265SDimitry Andric         break;
51481ad6265SDimitry Andric       case 32:
51581ad6265SDimitry Andric         VTM = VectorTypeModifier::FixedSEW32;
51681ad6265SDimitry Andric         break;
51781ad6265SDimitry Andric       case 64:
51881ad6265SDimitry Andric         VTM = VectorTypeModifier::FixedSEW64;
51981ad6265SDimitry Andric         break;
52081ad6265SDimitry Andric       default:
52181ad6265SDimitry Andric         llvm_unreachable("Invalid FixedSEW value, should be 8, 16, 32 or 64");
522bdd1243dSDimitry Andric         return std::nullopt;
52381ad6265SDimitry Andric       }
52481ad6265SDimitry Andric     } else if (ComplexTT.first == "LFixedLog2LMUL") {
52581ad6265SDimitry Andric       int32_t Log2LMUL;
52681ad6265SDimitry Andric       if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
52781ad6265SDimitry Andric         llvm_unreachable("Invalid LFixedLog2LMUL value!");
528bdd1243dSDimitry Andric         return std::nullopt;
52981ad6265SDimitry Andric       }
53081ad6265SDimitry Andric       switch (Log2LMUL) {
53181ad6265SDimitry Andric       case -3:
53281ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMULN3;
53381ad6265SDimitry Andric         break;
53481ad6265SDimitry Andric       case -2:
53581ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMULN2;
53681ad6265SDimitry Andric         break;
53781ad6265SDimitry Andric       case -1:
53881ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMULN1;
53981ad6265SDimitry Andric         break;
54081ad6265SDimitry Andric       case 0:
54181ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMUL0;
54281ad6265SDimitry Andric         break;
54381ad6265SDimitry Andric       case 1:
54481ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMUL1;
54581ad6265SDimitry Andric         break;
54681ad6265SDimitry Andric       case 2:
54781ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMUL2;
54881ad6265SDimitry Andric         break;
54981ad6265SDimitry Andric       case 3:
55081ad6265SDimitry Andric         VTM = VectorTypeModifier::LFixedLog2LMUL3;
55181ad6265SDimitry Andric         break;
55281ad6265SDimitry Andric       default:
55381ad6265SDimitry Andric         llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
554bdd1243dSDimitry Andric         return std::nullopt;
55581ad6265SDimitry Andric       }
55681ad6265SDimitry Andric     } else if (ComplexTT.first == "SFixedLog2LMUL") {
55781ad6265SDimitry Andric       int32_t Log2LMUL;
55881ad6265SDimitry Andric       if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
55981ad6265SDimitry Andric         llvm_unreachable("Invalid SFixedLog2LMUL value!");
560bdd1243dSDimitry Andric         return std::nullopt;
56181ad6265SDimitry Andric       }
56281ad6265SDimitry Andric       switch (Log2LMUL) {
56381ad6265SDimitry Andric       case -3:
56481ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMULN3;
56581ad6265SDimitry Andric         break;
56681ad6265SDimitry Andric       case -2:
56781ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMULN2;
56881ad6265SDimitry Andric         break;
56981ad6265SDimitry Andric       case -1:
57081ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMULN1;
57181ad6265SDimitry Andric         break;
57281ad6265SDimitry Andric       case 0:
57381ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMUL0;
57481ad6265SDimitry Andric         break;
57581ad6265SDimitry Andric       case 1:
57681ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMUL1;
57781ad6265SDimitry Andric         break;
57881ad6265SDimitry Andric       case 2:
57981ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMUL2;
58081ad6265SDimitry Andric         break;
58181ad6265SDimitry Andric       case 3:
58281ad6265SDimitry Andric         VTM = VectorTypeModifier::SFixedLog2LMUL3;
58381ad6265SDimitry Andric         break;
58481ad6265SDimitry Andric       default:
58581ad6265SDimitry Andric         llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
586bdd1243dSDimitry Andric         return std::nullopt;
58781ad6265SDimitry Andric       }
58881ad6265SDimitry Andric 
5895f757f3fSDimitry Andric     } else if (ComplexTT.first == "SEFixedLog2LMUL") {
5905f757f3fSDimitry Andric       int32_t Log2LMUL;
5915f757f3fSDimitry Andric       if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
5925f757f3fSDimitry Andric         llvm_unreachable("Invalid SEFixedLog2LMUL value!");
5935f757f3fSDimitry Andric         return std::nullopt;
5945f757f3fSDimitry Andric       }
5955f757f3fSDimitry Andric       switch (Log2LMUL) {
5965f757f3fSDimitry Andric       case -3:
5975f757f3fSDimitry Andric         VTM = VectorTypeModifier::SEFixedLog2LMULN3;
5985f757f3fSDimitry Andric         break;
5995f757f3fSDimitry Andric       case -2:
6005f757f3fSDimitry Andric         VTM = VectorTypeModifier::SEFixedLog2LMULN2;
6015f757f3fSDimitry Andric         break;
6025f757f3fSDimitry Andric       case -1:
6035f757f3fSDimitry Andric         VTM = VectorTypeModifier::SEFixedLog2LMULN1;
6045f757f3fSDimitry Andric         break;
6055f757f3fSDimitry Andric       case 0:
6065f757f3fSDimitry Andric         VTM = VectorTypeModifier::SEFixedLog2LMUL0;
6075f757f3fSDimitry Andric         break;
6085f757f3fSDimitry Andric       case 1:
6095f757f3fSDimitry Andric         VTM = VectorTypeModifier::SEFixedLog2LMUL1;
6105f757f3fSDimitry Andric         break;
6115f757f3fSDimitry Andric       case 2:
6125f757f3fSDimitry Andric         VTM = VectorTypeModifier::SEFixedLog2LMUL2;
6135f757f3fSDimitry Andric         break;
6145f757f3fSDimitry Andric       case 3:
6155f757f3fSDimitry Andric         VTM = VectorTypeModifier::SEFixedLog2LMUL3;
6165f757f3fSDimitry Andric         break;
6175f757f3fSDimitry Andric       default:
6185f757f3fSDimitry Andric         llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]");
6195f757f3fSDimitry Andric         return std::nullopt;
6205f757f3fSDimitry Andric       }
62106c3fb27SDimitry Andric     } else if (ComplexTT.first == "Tuple") {
62206c3fb27SDimitry Andric       unsigned NF = 0;
62306c3fb27SDimitry Andric       if (ComplexTT.second.getAsInteger(10, NF)) {
62406c3fb27SDimitry Andric         llvm_unreachable("Invalid NF value!");
62506c3fb27SDimitry Andric         return std::nullopt;
62606c3fb27SDimitry Andric       }
62706c3fb27SDimitry Andric       VTM = getTupleVTM(NF);
62881ad6265SDimitry Andric     } else {
62981ad6265SDimitry Andric       llvm_unreachable("Illegal complex type transformers!");
63081ad6265SDimitry Andric     }
63181ad6265SDimitry Andric   }
63281ad6265SDimitry Andric   PD.VTM = static_cast<uint8_t>(VTM);
63381ad6265SDimitry Andric 
63481ad6265SDimitry Andric   // Compute the remain type transformers
63581ad6265SDimitry Andric   TypeModifier TM = TypeModifier::NoModifier;
63681ad6265SDimitry Andric   for (char I : PrototypeDescriptorStr) {
63781ad6265SDimitry Andric     switch (I) {
63881ad6265SDimitry Andric     case 'P':
63981ad6265SDimitry Andric       if ((TM & TypeModifier::Const) == TypeModifier::Const)
64081ad6265SDimitry Andric         llvm_unreachable("'P' transformer cannot be used after 'C'");
64181ad6265SDimitry Andric       if ((TM & TypeModifier::Pointer) == TypeModifier::Pointer)
64281ad6265SDimitry Andric         llvm_unreachable("'P' transformer cannot be used twice");
64381ad6265SDimitry Andric       TM |= TypeModifier::Pointer;
64481ad6265SDimitry Andric       break;
64581ad6265SDimitry Andric     case 'C':
64681ad6265SDimitry Andric       TM |= TypeModifier::Const;
64781ad6265SDimitry Andric       break;
64881ad6265SDimitry Andric     case 'K':
64981ad6265SDimitry Andric       TM |= TypeModifier::Immediate;
65081ad6265SDimitry Andric       break;
65181ad6265SDimitry Andric     case 'U':
65281ad6265SDimitry Andric       TM |= TypeModifier::UnsignedInteger;
65381ad6265SDimitry Andric       break;
65481ad6265SDimitry Andric     case 'I':
65581ad6265SDimitry Andric       TM |= TypeModifier::SignedInteger;
65681ad6265SDimitry Andric       break;
65781ad6265SDimitry Andric     case 'F':
65881ad6265SDimitry Andric       TM |= TypeModifier::Float;
65981ad6265SDimitry Andric       break;
66081ad6265SDimitry Andric     case 'S':
66181ad6265SDimitry Andric       TM |= TypeModifier::LMUL1;
66281ad6265SDimitry Andric       break;
66381ad6265SDimitry Andric     default:
66481ad6265SDimitry Andric       llvm_unreachable("Illegal non-primitive type transformer!");
66581ad6265SDimitry Andric     }
66681ad6265SDimitry Andric   }
66781ad6265SDimitry Andric   PD.TM = static_cast<uint8_t>(TM);
66881ad6265SDimitry Andric 
66981ad6265SDimitry Andric   return PD;
67081ad6265SDimitry Andric }
67181ad6265SDimitry Andric 
applyModifier(const PrototypeDescriptor & Transformer)67281ad6265SDimitry Andric void RVVType::applyModifier(const PrototypeDescriptor &Transformer) {
67381ad6265SDimitry Andric   // Handle primitive type transformer
67481ad6265SDimitry Andric   switch (static_cast<BaseTypeModifier>(Transformer.PT)) {
67581ad6265SDimitry Andric   case BaseTypeModifier::Scalar:
67681ad6265SDimitry Andric     Scale = 0;
67781ad6265SDimitry Andric     break;
67881ad6265SDimitry Andric   case BaseTypeModifier::Vector:
67981ad6265SDimitry Andric     Scale = LMUL.getScale(ElementBitwidth);
68081ad6265SDimitry Andric     break;
68181ad6265SDimitry Andric   case BaseTypeModifier::Void:
68281ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Void;
68381ad6265SDimitry Andric     break;
68481ad6265SDimitry Andric   case BaseTypeModifier::SizeT:
68581ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Size_t;
68681ad6265SDimitry Andric     break;
68781ad6265SDimitry Andric   case BaseTypeModifier::Ptrdiff:
68881ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Ptrdiff_t;
68981ad6265SDimitry Andric     break;
69081ad6265SDimitry Andric   case BaseTypeModifier::UnsignedLong:
69181ad6265SDimitry Andric     ScalarType = ScalarTypeKind::UnsignedLong;
69281ad6265SDimitry Andric     break;
69381ad6265SDimitry Andric   case BaseTypeModifier::SignedLong:
69481ad6265SDimitry Andric     ScalarType = ScalarTypeKind::SignedLong;
69581ad6265SDimitry Andric     break;
6965f757f3fSDimitry Andric   case BaseTypeModifier::Float32:
6975f757f3fSDimitry Andric     ElementBitwidth = 32;
6985f757f3fSDimitry Andric     ScalarType = ScalarTypeKind::Float;
6995f757f3fSDimitry Andric     break;
70081ad6265SDimitry Andric   case BaseTypeModifier::Invalid:
70181ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Invalid;
70281ad6265SDimitry Andric     return;
70381ad6265SDimitry Andric   }
70481ad6265SDimitry Andric 
70581ad6265SDimitry Andric   switch (static_cast<VectorTypeModifier>(Transformer.VTM)) {
70681ad6265SDimitry Andric   case VectorTypeModifier::Widening2XVector:
70781ad6265SDimitry Andric     ElementBitwidth *= 2;
70881ad6265SDimitry Andric     LMUL.MulLog2LMUL(1);
70981ad6265SDimitry Andric     Scale = LMUL.getScale(ElementBitwidth);
71081ad6265SDimitry Andric     break;
71181ad6265SDimitry Andric   case VectorTypeModifier::Widening4XVector:
71281ad6265SDimitry Andric     ElementBitwidth *= 4;
71381ad6265SDimitry Andric     LMUL.MulLog2LMUL(2);
71481ad6265SDimitry Andric     Scale = LMUL.getScale(ElementBitwidth);
71581ad6265SDimitry Andric     break;
71681ad6265SDimitry Andric   case VectorTypeModifier::Widening8XVector:
71781ad6265SDimitry Andric     ElementBitwidth *= 8;
71881ad6265SDimitry Andric     LMUL.MulLog2LMUL(3);
71981ad6265SDimitry Andric     Scale = LMUL.getScale(ElementBitwidth);
72081ad6265SDimitry Andric     break;
72181ad6265SDimitry Andric   case VectorTypeModifier::MaskVector:
72281ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Boolean;
72381ad6265SDimitry Andric     Scale = LMUL.getScale(ElementBitwidth);
72481ad6265SDimitry Andric     ElementBitwidth = 1;
72581ad6265SDimitry Andric     break;
72681ad6265SDimitry Andric   case VectorTypeModifier::Log2EEW3:
72781ad6265SDimitry Andric     applyLog2EEW(3);
72881ad6265SDimitry Andric     break;
72981ad6265SDimitry Andric   case VectorTypeModifier::Log2EEW4:
73081ad6265SDimitry Andric     applyLog2EEW(4);
73181ad6265SDimitry Andric     break;
73281ad6265SDimitry Andric   case VectorTypeModifier::Log2EEW5:
73381ad6265SDimitry Andric     applyLog2EEW(5);
73481ad6265SDimitry Andric     break;
73581ad6265SDimitry Andric   case VectorTypeModifier::Log2EEW6:
73681ad6265SDimitry Andric     applyLog2EEW(6);
73781ad6265SDimitry Andric     break;
73881ad6265SDimitry Andric   case VectorTypeModifier::FixedSEW8:
73981ad6265SDimitry Andric     applyFixedSEW(8);
74081ad6265SDimitry Andric     break;
74181ad6265SDimitry Andric   case VectorTypeModifier::FixedSEW16:
74281ad6265SDimitry Andric     applyFixedSEW(16);
74381ad6265SDimitry Andric     break;
74481ad6265SDimitry Andric   case VectorTypeModifier::FixedSEW32:
74581ad6265SDimitry Andric     applyFixedSEW(32);
74681ad6265SDimitry Andric     break;
74781ad6265SDimitry Andric   case VectorTypeModifier::FixedSEW64:
74881ad6265SDimitry Andric     applyFixedSEW(64);
74981ad6265SDimitry Andric     break;
75081ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMULN3:
75181ad6265SDimitry Andric     applyFixedLog2LMUL(-3, FixedLMULType::LargerThan);
75281ad6265SDimitry Andric     break;
75381ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMULN2:
75481ad6265SDimitry Andric     applyFixedLog2LMUL(-2, FixedLMULType::LargerThan);
75581ad6265SDimitry Andric     break;
75681ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMULN1:
75781ad6265SDimitry Andric     applyFixedLog2LMUL(-1, FixedLMULType::LargerThan);
75881ad6265SDimitry Andric     break;
75981ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMUL0:
76081ad6265SDimitry Andric     applyFixedLog2LMUL(0, FixedLMULType::LargerThan);
76181ad6265SDimitry Andric     break;
76281ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMUL1:
76381ad6265SDimitry Andric     applyFixedLog2LMUL(1, FixedLMULType::LargerThan);
76481ad6265SDimitry Andric     break;
76581ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMUL2:
76681ad6265SDimitry Andric     applyFixedLog2LMUL(2, FixedLMULType::LargerThan);
76781ad6265SDimitry Andric     break;
76881ad6265SDimitry Andric   case VectorTypeModifier::LFixedLog2LMUL3:
76981ad6265SDimitry Andric     applyFixedLog2LMUL(3, FixedLMULType::LargerThan);
77081ad6265SDimitry Andric     break;
77181ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMULN3:
77281ad6265SDimitry Andric     applyFixedLog2LMUL(-3, FixedLMULType::SmallerThan);
77381ad6265SDimitry Andric     break;
77481ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMULN2:
77581ad6265SDimitry Andric     applyFixedLog2LMUL(-2, FixedLMULType::SmallerThan);
77681ad6265SDimitry Andric     break;
77781ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMULN1:
77881ad6265SDimitry Andric     applyFixedLog2LMUL(-1, FixedLMULType::SmallerThan);
77981ad6265SDimitry Andric     break;
78081ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMUL0:
78181ad6265SDimitry Andric     applyFixedLog2LMUL(0, FixedLMULType::SmallerThan);
78281ad6265SDimitry Andric     break;
78381ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMUL1:
78481ad6265SDimitry Andric     applyFixedLog2LMUL(1, FixedLMULType::SmallerThan);
78581ad6265SDimitry Andric     break;
78681ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMUL2:
78781ad6265SDimitry Andric     applyFixedLog2LMUL(2, FixedLMULType::SmallerThan);
78881ad6265SDimitry Andric     break;
78981ad6265SDimitry Andric   case VectorTypeModifier::SFixedLog2LMUL3:
79081ad6265SDimitry Andric     applyFixedLog2LMUL(3, FixedLMULType::SmallerThan);
79181ad6265SDimitry Andric     break;
7925f757f3fSDimitry Andric   case VectorTypeModifier::SEFixedLog2LMULN3:
7935f757f3fSDimitry Andric     applyFixedLog2LMUL(-3, FixedLMULType::SmallerOrEqual);
7945f757f3fSDimitry Andric     break;
7955f757f3fSDimitry Andric   case VectorTypeModifier::SEFixedLog2LMULN2:
7965f757f3fSDimitry Andric     applyFixedLog2LMUL(-2, FixedLMULType::SmallerOrEqual);
7975f757f3fSDimitry Andric     break;
7985f757f3fSDimitry Andric   case VectorTypeModifier::SEFixedLog2LMULN1:
7995f757f3fSDimitry Andric     applyFixedLog2LMUL(-1, FixedLMULType::SmallerOrEqual);
8005f757f3fSDimitry Andric     break;
8015f757f3fSDimitry Andric   case VectorTypeModifier::SEFixedLog2LMUL0:
8025f757f3fSDimitry Andric     applyFixedLog2LMUL(0, FixedLMULType::SmallerOrEqual);
8035f757f3fSDimitry Andric     break;
8045f757f3fSDimitry Andric   case VectorTypeModifier::SEFixedLog2LMUL1:
8055f757f3fSDimitry Andric     applyFixedLog2LMUL(1, FixedLMULType::SmallerOrEqual);
8065f757f3fSDimitry Andric     break;
8075f757f3fSDimitry Andric   case VectorTypeModifier::SEFixedLog2LMUL2:
8085f757f3fSDimitry Andric     applyFixedLog2LMUL(2, FixedLMULType::SmallerOrEqual);
8095f757f3fSDimitry Andric     break;
8105f757f3fSDimitry Andric   case VectorTypeModifier::SEFixedLog2LMUL3:
8115f757f3fSDimitry Andric     applyFixedLog2LMUL(3, FixedLMULType::SmallerOrEqual);
8125f757f3fSDimitry Andric     break;
81306c3fb27SDimitry Andric   case VectorTypeModifier::Tuple2:
81406c3fb27SDimitry Andric   case VectorTypeModifier::Tuple3:
81506c3fb27SDimitry Andric   case VectorTypeModifier::Tuple4:
81606c3fb27SDimitry Andric   case VectorTypeModifier::Tuple5:
81706c3fb27SDimitry Andric   case VectorTypeModifier::Tuple6:
81806c3fb27SDimitry Andric   case VectorTypeModifier::Tuple7:
81906c3fb27SDimitry Andric   case VectorTypeModifier::Tuple8: {
82006c3fb27SDimitry Andric     IsTuple = true;
82106c3fb27SDimitry Andric     NF = 2 + static_cast<uint8_t>(Transformer.VTM) -
82206c3fb27SDimitry Andric          static_cast<uint8_t>(VectorTypeModifier::Tuple2);
82306c3fb27SDimitry Andric     break;
82406c3fb27SDimitry Andric   }
82581ad6265SDimitry Andric   case VectorTypeModifier::NoModifier:
82681ad6265SDimitry Andric     break;
82781ad6265SDimitry Andric   }
82881ad6265SDimitry Andric 
8295f757f3fSDimitry Andric   // Early return if the current type modifier is already invalid.
8305f757f3fSDimitry Andric   if (ScalarType == Invalid)
8315f757f3fSDimitry Andric     return;
8325f757f3fSDimitry Andric 
83381ad6265SDimitry Andric   for (unsigned TypeModifierMaskShift = 0;
83481ad6265SDimitry Andric        TypeModifierMaskShift <= static_cast<unsigned>(TypeModifier::MaxOffset);
83581ad6265SDimitry Andric        ++TypeModifierMaskShift) {
83681ad6265SDimitry Andric     unsigned TypeModifierMask = 1 << TypeModifierMaskShift;
83781ad6265SDimitry Andric     if ((static_cast<unsigned>(Transformer.TM) & TypeModifierMask) !=
83881ad6265SDimitry Andric         TypeModifierMask)
83981ad6265SDimitry Andric       continue;
84081ad6265SDimitry Andric     switch (static_cast<TypeModifier>(TypeModifierMask)) {
84181ad6265SDimitry Andric     case TypeModifier::Pointer:
84281ad6265SDimitry Andric       IsPointer = true;
84381ad6265SDimitry Andric       break;
84481ad6265SDimitry Andric     case TypeModifier::Const:
84581ad6265SDimitry Andric       IsConstant = true;
84681ad6265SDimitry Andric       break;
84781ad6265SDimitry Andric     case TypeModifier::Immediate:
84881ad6265SDimitry Andric       IsImmediate = true;
84981ad6265SDimitry Andric       IsConstant = true;
85081ad6265SDimitry Andric       break;
85181ad6265SDimitry Andric     case TypeModifier::UnsignedInteger:
85281ad6265SDimitry Andric       ScalarType = ScalarTypeKind::UnsignedInteger;
85381ad6265SDimitry Andric       break;
85481ad6265SDimitry Andric     case TypeModifier::SignedInteger:
85581ad6265SDimitry Andric       ScalarType = ScalarTypeKind::SignedInteger;
85681ad6265SDimitry Andric       break;
85781ad6265SDimitry Andric     case TypeModifier::Float:
85881ad6265SDimitry Andric       ScalarType = ScalarTypeKind::Float;
85981ad6265SDimitry Andric       break;
8605f757f3fSDimitry Andric     case TypeModifier::BFloat:
8615f757f3fSDimitry Andric       ScalarType = ScalarTypeKind::BFloat;
8625f757f3fSDimitry Andric       break;
86381ad6265SDimitry Andric     case TypeModifier::LMUL1:
86481ad6265SDimitry Andric       LMUL = LMULType(0);
86581ad6265SDimitry Andric       // Update ElementBitwidth need to update Scale too.
86681ad6265SDimitry Andric       Scale = LMUL.getScale(ElementBitwidth);
86781ad6265SDimitry Andric       break;
86881ad6265SDimitry Andric     default:
86981ad6265SDimitry Andric       llvm_unreachable("Unknown type modifier mask!");
87081ad6265SDimitry Andric     }
87181ad6265SDimitry Andric   }
87281ad6265SDimitry Andric }
87381ad6265SDimitry Andric 
applyLog2EEW(unsigned Log2EEW)87481ad6265SDimitry Andric void RVVType::applyLog2EEW(unsigned Log2EEW) {
87581ad6265SDimitry Andric   // update new elmul = (eew/sew) * lmul
87681ad6265SDimitry Andric   LMUL.MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth));
87781ad6265SDimitry Andric   // update new eew
87881ad6265SDimitry Andric   ElementBitwidth = 1 << Log2EEW;
87981ad6265SDimitry Andric   ScalarType = ScalarTypeKind::SignedInteger;
88081ad6265SDimitry Andric   Scale = LMUL.getScale(ElementBitwidth);
88181ad6265SDimitry Andric }
88281ad6265SDimitry Andric 
applyFixedSEW(unsigned NewSEW)88381ad6265SDimitry Andric void RVVType::applyFixedSEW(unsigned NewSEW) {
88481ad6265SDimitry Andric   // Set invalid type if src and dst SEW are same.
88581ad6265SDimitry Andric   if (ElementBitwidth == NewSEW) {
88681ad6265SDimitry Andric     ScalarType = ScalarTypeKind::Invalid;
88781ad6265SDimitry Andric     return;
88881ad6265SDimitry Andric   }
88981ad6265SDimitry Andric   // Update new SEW
89081ad6265SDimitry Andric   ElementBitwidth = NewSEW;
89181ad6265SDimitry Andric   Scale = LMUL.getScale(ElementBitwidth);
89281ad6265SDimitry Andric }
89381ad6265SDimitry Andric 
applyFixedLog2LMUL(int Log2LMUL,enum FixedLMULType Type)89481ad6265SDimitry Andric void RVVType::applyFixedLog2LMUL(int Log2LMUL, enum FixedLMULType Type) {
89581ad6265SDimitry Andric   switch (Type) {
89681ad6265SDimitry Andric   case FixedLMULType::LargerThan:
8975f757f3fSDimitry Andric     if (Log2LMUL <= LMUL.Log2LMUL) {
89881ad6265SDimitry Andric       ScalarType = ScalarTypeKind::Invalid;
89981ad6265SDimitry Andric       return;
90081ad6265SDimitry Andric     }
90181ad6265SDimitry Andric     break;
90281ad6265SDimitry Andric   case FixedLMULType::SmallerThan:
9035f757f3fSDimitry Andric     if (Log2LMUL >= LMUL.Log2LMUL) {
9045f757f3fSDimitry Andric       ScalarType = ScalarTypeKind::Invalid;
9055f757f3fSDimitry Andric       return;
9065f757f3fSDimitry Andric     }
9075f757f3fSDimitry Andric     break;
9085f757f3fSDimitry Andric   case FixedLMULType::SmallerOrEqual:
90981ad6265SDimitry Andric     if (Log2LMUL > LMUL.Log2LMUL) {
91081ad6265SDimitry Andric       ScalarType = ScalarTypeKind::Invalid;
91181ad6265SDimitry Andric       return;
91281ad6265SDimitry Andric     }
91381ad6265SDimitry Andric     break;
91481ad6265SDimitry Andric   }
91581ad6265SDimitry Andric 
91681ad6265SDimitry Andric   // Update new LMUL
91781ad6265SDimitry Andric   LMUL = LMULType(Log2LMUL);
91881ad6265SDimitry Andric   Scale = LMUL.getScale(ElementBitwidth);
91981ad6265SDimitry Andric }
92081ad6265SDimitry Andric 
921bdd1243dSDimitry Andric std::optional<RVVTypes>
computeTypes(BasicType BT,int Log2LMUL,unsigned NF,ArrayRef<PrototypeDescriptor> Prototype)922bdd1243dSDimitry Andric RVVTypeCache::computeTypes(BasicType BT, int Log2LMUL, unsigned NF,
92381ad6265SDimitry Andric                            ArrayRef<PrototypeDescriptor> Prototype) {
92481ad6265SDimitry Andric   RVVTypes Types;
92581ad6265SDimitry Andric   for (const PrototypeDescriptor &Proto : Prototype) {
92681ad6265SDimitry Andric     auto T = computeType(BT, Log2LMUL, Proto);
92781ad6265SDimitry Andric     if (!T)
928bdd1243dSDimitry Andric       return std::nullopt;
92981ad6265SDimitry Andric     // Record legal type index
930bdd1243dSDimitry Andric     Types.push_back(*T);
93181ad6265SDimitry Andric   }
93281ad6265SDimitry Andric   return Types;
93381ad6265SDimitry Andric }
93481ad6265SDimitry Andric 
93581ad6265SDimitry Andric // Compute the hash value of RVVType, used for cache the result of computeType.
computeRVVTypeHashValue(BasicType BT,int Log2LMUL,PrototypeDescriptor Proto)93681ad6265SDimitry Andric static uint64_t computeRVVTypeHashValue(BasicType BT, int Log2LMUL,
93781ad6265SDimitry Andric                                         PrototypeDescriptor Proto) {
93881ad6265SDimitry Andric   // Layout of hash value:
93981ad6265SDimitry Andric   // 0               8    16          24        32          40
94081ad6265SDimitry Andric   // | Log2LMUL + 3  | BT  | Proto.PT | Proto.TM | Proto.VTM |
94181ad6265SDimitry Andric   assert(Log2LMUL >= -3 && Log2LMUL <= 3);
94281ad6265SDimitry Andric   return (Log2LMUL + 3) | (static_cast<uint64_t>(BT) & 0xff) << 8 |
94381ad6265SDimitry Andric          ((uint64_t)(Proto.PT & 0xff) << 16) |
94481ad6265SDimitry Andric          ((uint64_t)(Proto.TM & 0xff) << 24) |
94581ad6265SDimitry Andric          ((uint64_t)(Proto.VTM & 0xff) << 32);
94681ad6265SDimitry Andric }
94781ad6265SDimitry Andric 
computeType(BasicType BT,int Log2LMUL,PrototypeDescriptor Proto)948bdd1243dSDimitry Andric std::optional<RVVTypePtr> RVVTypeCache::computeType(BasicType BT, int Log2LMUL,
94981ad6265SDimitry Andric                                                     PrototypeDescriptor Proto) {
95081ad6265SDimitry Andric   uint64_t Idx = computeRVVTypeHashValue(BT, Log2LMUL, Proto);
95181ad6265SDimitry Andric   // Search first
95281ad6265SDimitry Andric   auto It = LegalTypes.find(Idx);
95381ad6265SDimitry Andric   if (It != LegalTypes.end())
95481ad6265SDimitry Andric     return &(It->second);
95581ad6265SDimitry Andric 
95681ad6265SDimitry Andric   if (IllegalTypes.count(Idx))
957bdd1243dSDimitry Andric     return std::nullopt;
95881ad6265SDimitry Andric 
95981ad6265SDimitry Andric   // Compute type and record the result.
96081ad6265SDimitry Andric   RVVType T(BT, Log2LMUL, Proto);
96181ad6265SDimitry Andric   if (T.isValid()) {
96281ad6265SDimitry Andric     // Record legal type index and value.
963bdd1243dSDimitry Andric     std::pair<std::unordered_map<uint64_t, RVVType>::iterator, bool>
964bdd1243dSDimitry Andric         InsertResult = LegalTypes.insert({Idx, T});
965bdd1243dSDimitry Andric     return &(InsertResult.first->second);
96681ad6265SDimitry Andric   }
96781ad6265SDimitry Andric   // Record illegal type index.
96881ad6265SDimitry Andric   IllegalTypes.insert(Idx);
969bdd1243dSDimitry Andric   return std::nullopt;
97081ad6265SDimitry Andric }
97181ad6265SDimitry Andric 
97281ad6265SDimitry Andric //===----------------------------------------------------------------------===//
97381ad6265SDimitry Andric // RVVIntrinsic implementation
97481ad6265SDimitry Andric //===----------------------------------------------------------------------===//
RVVIntrinsic(StringRef NewName,StringRef Suffix,StringRef NewOverloadedName,StringRef OverloadedSuffix,StringRef IRName,bool IsMasked,bool HasMaskedOffOperand,bool HasVL,PolicyScheme Scheme,bool SupportOverloading,bool HasBuiltinAlias,StringRef ManualCodegen,const RVVTypes & OutInTypes,const std::vector<int64_t> & NewIntrinsicTypes,unsigned NF,Policy NewPolicyAttrs,bool HasFRMRoundModeOp)97506c3fb27SDimitry Andric RVVIntrinsic::RVVIntrinsic(
97606c3fb27SDimitry Andric     StringRef NewName, StringRef Suffix, StringRef NewOverloadedName,
97706c3fb27SDimitry Andric     StringRef OverloadedSuffix, StringRef IRName, bool IsMasked,
97806c3fb27SDimitry Andric     bool HasMaskedOffOperand, bool HasVL, PolicyScheme Scheme,
97906c3fb27SDimitry Andric     bool SupportOverloading, bool HasBuiltinAlias, StringRef ManualCodegen,
98006c3fb27SDimitry Andric     const RVVTypes &OutInTypes, const std::vector<int64_t> &NewIntrinsicTypes,
981*0fca6ea1SDimitry Andric     unsigned NF, Policy NewPolicyAttrs, bool HasFRMRoundModeOp)
982bdd1243dSDimitry Andric     : IRName(IRName), IsMasked(IsMasked),
983bdd1243dSDimitry Andric       HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme),
984bdd1243dSDimitry Andric       SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias),
985bdd1243dSDimitry Andric       ManualCodegen(ManualCodegen.str()), NF(NF), PolicyAttrs(NewPolicyAttrs) {
98681ad6265SDimitry Andric 
98781ad6265SDimitry Andric   // Init BuiltinName, Name and OverloadedName
98881ad6265SDimitry Andric   BuiltinName = NewName.str();
98981ad6265SDimitry Andric   Name = BuiltinName;
99081ad6265SDimitry Andric   if (NewOverloadedName.empty())
99181ad6265SDimitry Andric     OverloadedName = NewName.split("_").first.str();
99281ad6265SDimitry Andric   else
99381ad6265SDimitry Andric     OverloadedName = NewOverloadedName.str();
99481ad6265SDimitry Andric   if (!Suffix.empty())
99581ad6265SDimitry Andric     Name += "_" + Suffix.str();
99681ad6265SDimitry Andric   if (!OverloadedSuffix.empty())
99781ad6265SDimitry Andric     OverloadedName += "_" + OverloadedSuffix.str();
998bdd1243dSDimitry Andric 
999bdd1243dSDimitry Andric   updateNamesAndPolicy(IsMasked, hasPolicy(), Name, BuiltinName, OverloadedName,
100006c3fb27SDimitry Andric                        PolicyAttrs, HasFRMRoundModeOp);
100181ad6265SDimitry Andric 
100281ad6265SDimitry Andric   // Init OutputType and InputTypes
100381ad6265SDimitry Andric   OutputType = OutInTypes[0];
100481ad6265SDimitry Andric   InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
100581ad6265SDimitry Andric 
100681ad6265SDimitry Andric   // IntrinsicTypes is unmasked TA version index. Need to update it
100781ad6265SDimitry Andric   // if there is merge operand (It is always in first operand).
100881ad6265SDimitry Andric   IntrinsicTypes = NewIntrinsicTypes;
1009bdd1243dSDimitry Andric   if ((IsMasked && hasMaskedOffOperand()) ||
101081ad6265SDimitry Andric       (!IsMasked && hasPassthruOperand())) {
101181ad6265SDimitry Andric     for (auto &I : IntrinsicTypes) {
101281ad6265SDimitry Andric       if (I >= 0)
101381ad6265SDimitry Andric         I += NF;
101481ad6265SDimitry Andric     }
101581ad6265SDimitry Andric   }
101681ad6265SDimitry Andric }
101781ad6265SDimitry Andric 
getBuiltinTypeStr() const101881ad6265SDimitry Andric std::string RVVIntrinsic::getBuiltinTypeStr() const {
101981ad6265SDimitry Andric   std::string S;
102081ad6265SDimitry Andric   S += OutputType->getBuiltinStr();
102181ad6265SDimitry Andric   for (const auto &T : InputTypes) {
102281ad6265SDimitry Andric     S += T->getBuiltinStr();
102381ad6265SDimitry Andric   }
102481ad6265SDimitry Andric   return S;
102581ad6265SDimitry Andric }
102681ad6265SDimitry Andric 
getSuffixStr(RVVTypeCache & TypeCache,BasicType Type,int Log2LMUL,llvm::ArrayRef<PrototypeDescriptor> PrototypeDescriptors)102781ad6265SDimitry Andric std::string RVVIntrinsic::getSuffixStr(
1028bdd1243dSDimitry Andric     RVVTypeCache &TypeCache, BasicType Type, int Log2LMUL,
102981ad6265SDimitry Andric     llvm::ArrayRef<PrototypeDescriptor> PrototypeDescriptors) {
103081ad6265SDimitry Andric   SmallVector<std::string> SuffixStrs;
103181ad6265SDimitry Andric   for (auto PD : PrototypeDescriptors) {
1032bdd1243dSDimitry Andric     auto T = TypeCache.computeType(Type, Log2LMUL, PD);
103381ad6265SDimitry Andric     SuffixStrs.push_back((*T)->getShortStr());
103481ad6265SDimitry Andric   }
103581ad6265SDimitry Andric   return join(SuffixStrs, "_");
103681ad6265SDimitry Andric }
103781ad6265SDimitry Andric 
computeBuiltinTypes(llvm::ArrayRef<PrototypeDescriptor> Prototype,bool IsMasked,bool HasMaskedOffOperand,bool HasVL,unsigned NF,PolicyScheme DefaultScheme,Policy PolicyAttrs,bool IsTuple)1038bdd1243dSDimitry Andric llvm::SmallVector<PrototypeDescriptor> RVVIntrinsic::computeBuiltinTypes(
1039bdd1243dSDimitry Andric     llvm::ArrayRef<PrototypeDescriptor> Prototype, bool IsMasked,
1040bdd1243dSDimitry Andric     bool HasMaskedOffOperand, bool HasVL, unsigned NF,
104106c3fb27SDimitry Andric     PolicyScheme DefaultScheme, Policy PolicyAttrs, bool IsTuple) {
1042972a253aSDimitry Andric   SmallVector<PrototypeDescriptor> NewPrototype(Prototype.begin(),
1043972a253aSDimitry Andric                                                 Prototype.end());
1044bdd1243dSDimitry Andric   bool HasPassthruOp = DefaultScheme == PolicyScheme::HasPassthruOperand;
1045972a253aSDimitry Andric   if (IsMasked) {
1046bdd1243dSDimitry Andric     // If HasMaskedOffOperand, insert result type as first input operand if
1047bdd1243dSDimitry Andric     // need.
1048bdd1243dSDimitry Andric     if (HasMaskedOffOperand && !PolicyAttrs.isTAMAPolicy()) {
1049972a253aSDimitry Andric       if (NF == 1) {
1050972a253aSDimitry Andric         NewPrototype.insert(NewPrototype.begin() + 1, NewPrototype[0]);
1051bdd1243dSDimitry Andric       } else if (NF > 1) {
105206c3fb27SDimitry Andric         if (IsTuple) {
105306c3fb27SDimitry Andric           PrototypeDescriptor BasePtrOperand = Prototype[1];
105406c3fb27SDimitry Andric           PrototypeDescriptor MaskoffType = PrototypeDescriptor(
105506c3fb27SDimitry Andric               static_cast<uint8_t>(BaseTypeModifier::Vector),
105606c3fb27SDimitry Andric               static_cast<uint8_t>(getTupleVTM(NF)),
105706c3fb27SDimitry Andric               BasePtrOperand.TM & ~static_cast<uint8_t>(TypeModifier::Pointer));
105806c3fb27SDimitry Andric           NewPrototype.insert(NewPrototype.begin() + 1, MaskoffType);
105906c3fb27SDimitry Andric         } else {
1060972a253aSDimitry Andric           // Convert
1061972a253aSDimitry Andric           // (void, op0 address, op1 address, ...)
1062972a253aSDimitry Andric           // to
1063972a253aSDimitry Andric           // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
1064972a253aSDimitry Andric           PrototypeDescriptor MaskoffType = NewPrototype[1];
1065972a253aSDimitry Andric           MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer);
1066bdd1243dSDimitry Andric           NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1067972a253aSDimitry Andric         }
1068972a253aSDimitry Andric       }
106906c3fb27SDimitry Andric     }
1070972a253aSDimitry Andric     if (HasMaskedOffOperand && NF > 1) {
1071972a253aSDimitry Andric       // Convert
1072972a253aSDimitry Andric       // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...)
1073972a253aSDimitry Andric       // to
1074972a253aSDimitry Andric       // (void, op0 address, op1 address, ..., mask, maskedoff0, maskedoff1,
1075972a253aSDimitry Andric       // ...)
107606c3fb27SDimitry Andric       if (IsTuple)
107706c3fb27SDimitry Andric         NewPrototype.insert(NewPrototype.begin() + 1,
107806c3fb27SDimitry Andric                             PrototypeDescriptor::Mask);
107906c3fb27SDimitry Andric       else
1080972a253aSDimitry Andric         NewPrototype.insert(NewPrototype.begin() + NF + 1,
1081972a253aSDimitry Andric                             PrototypeDescriptor::Mask);
1082972a253aSDimitry Andric     } else {
1083972a253aSDimitry Andric       // If IsMasked, insert PrototypeDescriptor:Mask as first input operand.
1084972a253aSDimitry Andric       NewPrototype.insert(NewPrototype.begin() + 1, PrototypeDescriptor::Mask);
1085972a253aSDimitry Andric     }
1086bdd1243dSDimitry Andric   } else {
1087bdd1243dSDimitry Andric     if (NF == 1) {
1088bdd1243dSDimitry Andric       if (PolicyAttrs.isTUPolicy() && HasPassthruOp)
1089bdd1243dSDimitry Andric         NewPrototype.insert(NewPrototype.begin(), NewPrototype[0]);
1090bdd1243dSDimitry Andric     } else if (PolicyAttrs.isTUPolicy() && HasPassthruOp) {
109106c3fb27SDimitry Andric       if (IsTuple) {
109206c3fb27SDimitry Andric         PrototypeDescriptor BasePtrOperand = Prototype[0];
109306c3fb27SDimitry Andric         PrototypeDescriptor MaskoffType = PrototypeDescriptor(
109406c3fb27SDimitry Andric             static_cast<uint8_t>(BaseTypeModifier::Vector),
109506c3fb27SDimitry Andric             static_cast<uint8_t>(getTupleVTM(NF)),
109606c3fb27SDimitry Andric             BasePtrOperand.TM & ~static_cast<uint8_t>(TypeModifier::Pointer));
109706c3fb27SDimitry Andric         NewPrototype.insert(NewPrototype.begin(), MaskoffType);
109806c3fb27SDimitry Andric       } else {
1099bdd1243dSDimitry Andric         // NF > 1 cases for segment load operations.
1100bdd1243dSDimitry Andric         // Convert
1101bdd1243dSDimitry Andric         // (void, op0 address, op1 address, ...)
1102bdd1243dSDimitry Andric         // to
1103bdd1243dSDimitry Andric         // (void, op0 address, op1 address, maskedoff0, maskedoff1, ...)
1104bdd1243dSDimitry Andric         PrototypeDescriptor MaskoffType = Prototype[1];
1105bdd1243dSDimitry Andric         MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer);
1106bdd1243dSDimitry Andric         NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1107bdd1243dSDimitry Andric       }
1108972a253aSDimitry Andric     }
110906c3fb27SDimitry Andric  }
1110972a253aSDimitry Andric 
1111972a253aSDimitry Andric   // If HasVL, append PrototypeDescriptor:VL to last operand
1112972a253aSDimitry Andric   if (HasVL)
1113972a253aSDimitry Andric     NewPrototype.push_back(PrototypeDescriptor::VL);
111406c3fb27SDimitry Andric 
1115972a253aSDimitry Andric   return NewPrototype;
1116972a253aSDimitry Andric }
1117972a253aSDimitry Andric 
getSupportedUnMaskedPolicies()11181ac55f4cSDimitry Andric llvm::SmallVector<Policy> RVVIntrinsic::getSupportedUnMaskedPolicies() {
11191ac55f4cSDimitry Andric   return {Policy(Policy::PolicyType::Undisturbed)}; // TU
1120bdd1243dSDimitry Andric }
1121bdd1243dSDimitry Andric 
1122bdd1243dSDimitry Andric llvm::SmallVector<Policy>
getSupportedMaskedPolicies(bool HasTailPolicy,bool HasMaskPolicy)1123bdd1243dSDimitry Andric RVVIntrinsic::getSupportedMaskedPolicies(bool HasTailPolicy,
1124bdd1243dSDimitry Andric                                          bool HasMaskPolicy) {
1125bdd1243dSDimitry Andric   if (HasTailPolicy && HasMaskPolicy)
11261ac55f4cSDimitry Andric     return {Policy(Policy::PolicyType::Undisturbed,
11271ac55f4cSDimitry Andric                    Policy::PolicyType::Agnostic), // TUM
11281ac55f4cSDimitry Andric             Policy(Policy::PolicyType::Undisturbed,
11291ac55f4cSDimitry Andric                    Policy::PolicyType::Undisturbed), // TUMU
11301ac55f4cSDimitry Andric             Policy(Policy::PolicyType::Agnostic,
11311ac55f4cSDimitry Andric                    Policy::PolicyType::Undisturbed)}; // MU
1132bdd1243dSDimitry Andric   if (HasTailPolicy && !HasMaskPolicy)
1133bdd1243dSDimitry Andric     return {Policy(Policy::PolicyType::Undisturbed,
11341ac55f4cSDimitry Andric                    Policy::PolicyType::Agnostic)}; // TU
1135bdd1243dSDimitry Andric   if (!HasTailPolicy && HasMaskPolicy)
11361ac55f4cSDimitry Andric     return {Policy(Policy::PolicyType::Agnostic,
11371ac55f4cSDimitry Andric                    Policy::PolicyType::Undisturbed)}; // MU
1138bdd1243dSDimitry Andric   llvm_unreachable("An RVV instruction should not be without both tail policy "
1139bdd1243dSDimitry Andric                    "and mask policy");
1140bdd1243dSDimitry Andric }
1141bdd1243dSDimitry Andric 
updateNamesAndPolicy(bool IsMasked,bool HasPolicy,std::string & Name,std::string & BuiltinName,std::string & OverloadedName,Policy & PolicyAttrs,bool HasFRMRoundModeOp)114206c3fb27SDimitry Andric void RVVIntrinsic::updateNamesAndPolicy(
114306c3fb27SDimitry Andric     bool IsMasked, bool HasPolicy, std::string &Name, std::string &BuiltinName,
114406c3fb27SDimitry Andric     std::string &OverloadedName, Policy &PolicyAttrs, bool HasFRMRoundModeOp) {
1145bdd1243dSDimitry Andric 
1146bdd1243dSDimitry Andric   auto appendPolicySuffix = [&](const std::string &suffix) {
1147bdd1243dSDimitry Andric     Name += suffix;
1148bdd1243dSDimitry Andric     BuiltinName += suffix;
1149bdd1243dSDimitry Andric     OverloadedName += suffix;
1150bdd1243dSDimitry Andric   };
1151bdd1243dSDimitry Andric 
115206c3fb27SDimitry Andric   if (HasFRMRoundModeOp) {
115306c3fb27SDimitry Andric     Name += "_rm";
115406c3fb27SDimitry Andric     BuiltinName += "_rm";
115506c3fb27SDimitry Andric   }
115606c3fb27SDimitry Andric 
1157bdd1243dSDimitry Andric   if (IsMasked) {
11581ac55f4cSDimitry Andric     if (PolicyAttrs.isTUMUPolicy())
11591ac55f4cSDimitry Andric       appendPolicySuffix("_tumu");
11601ac55f4cSDimitry Andric     else if (PolicyAttrs.isTUMAPolicy())
11611ac55f4cSDimitry Andric       appendPolicySuffix("_tum");
11621ac55f4cSDimitry Andric     else if (PolicyAttrs.isTAMUPolicy())
11631ac55f4cSDimitry Andric       appendPolicySuffix("_mu");
11641ac55f4cSDimitry Andric     else if (PolicyAttrs.isTAMAPolicy()) {
1165bdd1243dSDimitry Andric       Name += "_m";
1166bdd1243dSDimitry Andric       BuiltinName += "_m";
11671ac55f4cSDimitry Andric     } else
1168bdd1243dSDimitry Andric       llvm_unreachable("Unhandled policy condition");
1169bdd1243dSDimitry Andric   } else {
1170bdd1243dSDimitry Andric     if (PolicyAttrs.isTUPolicy())
1171bdd1243dSDimitry Andric       appendPolicySuffix("_tu");
117206c3fb27SDimitry Andric     else if (PolicyAttrs.isTAPolicy()) // no suffix needed
117306c3fb27SDimitry Andric       return;
117406c3fb27SDimitry Andric     else
1175bdd1243dSDimitry Andric       llvm_unreachable("Unhandled policy condition");
1176bdd1243dSDimitry Andric   }
1177bdd1243dSDimitry Andric }
1178bdd1243dSDimitry Andric 
parsePrototypes(StringRef Prototypes)117981ad6265SDimitry Andric SmallVector<PrototypeDescriptor> parsePrototypes(StringRef Prototypes) {
118081ad6265SDimitry Andric   SmallVector<PrototypeDescriptor> PrototypeDescriptors;
11815f757f3fSDimitry Andric   const StringRef Primaries("evwqom0ztulf");
118281ad6265SDimitry Andric   while (!Prototypes.empty()) {
118381ad6265SDimitry Andric     size_t Idx = 0;
118481ad6265SDimitry Andric     // Skip over complex prototype because it could contain primitive type
118581ad6265SDimitry Andric     // character.
118681ad6265SDimitry Andric     if (Prototypes[0] == '(')
118781ad6265SDimitry Andric       Idx = Prototypes.find_first_of(')');
118881ad6265SDimitry Andric     Idx = Prototypes.find_first_of(Primaries, Idx);
118981ad6265SDimitry Andric     assert(Idx != StringRef::npos);
119081ad6265SDimitry Andric     auto PD = PrototypeDescriptor::parsePrototypeDescriptor(
119181ad6265SDimitry Andric         Prototypes.slice(0, Idx + 1));
119281ad6265SDimitry Andric     if (!PD)
119381ad6265SDimitry Andric       llvm_unreachable("Error during parsing prototype.");
119481ad6265SDimitry Andric     PrototypeDescriptors.push_back(*PD);
119581ad6265SDimitry Andric     Prototypes = Prototypes.drop_front(Idx + 1);
119681ad6265SDimitry Andric   }
119781ad6265SDimitry Andric   return PrototypeDescriptors;
119881ad6265SDimitry Andric }
119981ad6265SDimitry Andric 
operator <<(raw_ostream & OS,const RVVIntrinsicRecord & Record)1200972a253aSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const RVVIntrinsicRecord &Record) {
1201972a253aSDimitry Andric   OS << "{";
1202972a253aSDimitry Andric   OS << "\"" << Record.Name << "\",";
1203972a253aSDimitry Andric   if (Record.OverloadedName == nullptr ||
1204972a253aSDimitry Andric       StringRef(Record.OverloadedName).empty())
1205972a253aSDimitry Andric     OS << "nullptr,";
1206972a253aSDimitry Andric   else
1207972a253aSDimitry Andric     OS << "\"" << Record.OverloadedName << "\",";
1208972a253aSDimitry Andric   OS << Record.PrototypeIndex << ",";
1209972a253aSDimitry Andric   OS << Record.SuffixIndex << ",";
1210972a253aSDimitry Andric   OS << Record.OverloadedSuffixIndex << ",";
1211972a253aSDimitry Andric   OS << (int)Record.PrototypeLength << ",";
1212972a253aSDimitry Andric   OS << (int)Record.SuffixLength << ",";
1213972a253aSDimitry Andric   OS << (int)Record.OverloadedSuffixSize << ",";
1214cb14a3feSDimitry Andric   OS << Record.RequiredExtensions << ",";
1215972a253aSDimitry Andric   OS << (int)Record.TypeRangeMask << ",";
1216972a253aSDimitry Andric   OS << (int)Record.Log2LMULMask << ",";
1217972a253aSDimitry Andric   OS << (int)Record.NF << ",";
1218972a253aSDimitry Andric   OS << (int)Record.HasMasked << ",";
1219972a253aSDimitry Andric   OS << (int)Record.HasVL << ",";
1220972a253aSDimitry Andric   OS << (int)Record.HasMaskedOffOperand << ",";
1221bdd1243dSDimitry Andric   OS << (int)Record.HasTailPolicy << ",";
1222bdd1243dSDimitry Andric   OS << (int)Record.HasMaskPolicy << ",";
122306c3fb27SDimitry Andric   OS << (int)Record.HasFRMRoundModeOp << ",";
122406c3fb27SDimitry Andric   OS << (int)Record.IsTuple << ",";
1225bdd1243dSDimitry Andric   OS << (int)Record.UnMaskedPolicyScheme << ",";
1226bdd1243dSDimitry Andric   OS << (int)Record.MaskedPolicyScheme << ",";
1227972a253aSDimitry Andric   OS << "},\n";
1228972a253aSDimitry Andric   return OS;
1229972a253aSDimitry Andric }
1230972a253aSDimitry Andric 
123181ad6265SDimitry Andric } // end namespace RISCV
123281ad6265SDimitry Andric } // end namespace clang
1233