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