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