181ad6265SDimitry Andric //===- RISCVVIntrinsicUtils.cpp - RISC-V Vector Intrinsic Utils -*- C++ -*-===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric 981ad6265SDimitry Andric #include "clang/Support/RISCVVIntrinsicUtils.h" 1081ad6265SDimitry Andric #include "llvm/ADT/ArrayRef.h" 1181ad6265SDimitry Andric #include "llvm/ADT/SmallSet.h" 1281ad6265SDimitry Andric #include "llvm/ADT/StringExtras.h" 1381ad6265SDimitry Andric #include "llvm/ADT/StringMap.h" 1481ad6265SDimitry Andric #include "llvm/ADT/StringSet.h" 1581ad6265SDimitry Andric #include "llvm/ADT/Twine.h" 16bdd1243dSDimitry Andric #include "llvm/Support/ErrorHandling.h" 1781ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h" 1881ad6265SDimitry Andric #include <numeric> 19bdd1243dSDimitry Andric #include <optional> 2081ad6265SDimitry Andric 2181ad6265SDimitry Andric using namespace llvm; 2281ad6265SDimitry Andric 2381ad6265SDimitry Andric namespace clang { 2481ad6265SDimitry Andric namespace RISCV { 2581ad6265SDimitry Andric 2681ad6265SDimitry Andric const PrototypeDescriptor PrototypeDescriptor::Mask = PrototypeDescriptor( 2781ad6265SDimitry Andric BaseTypeModifier::Vector, VectorTypeModifier::MaskVector); 2881ad6265SDimitry Andric const PrototypeDescriptor PrototypeDescriptor::VL = 2981ad6265SDimitry Andric PrototypeDescriptor(BaseTypeModifier::SizeT); 3081ad6265SDimitry Andric const PrototypeDescriptor PrototypeDescriptor::Vector = 3181ad6265SDimitry Andric PrototypeDescriptor(BaseTypeModifier::Vector); 3281ad6265SDimitry Andric 3381ad6265SDimitry Andric //===----------------------------------------------------------------------===// 3481ad6265SDimitry Andric // Type implementation 3581ad6265SDimitry Andric //===----------------------------------------------------------------------===// 3681ad6265SDimitry Andric 3781ad6265SDimitry Andric LMULType::LMULType(int NewLog2LMUL) { 3881ad6265SDimitry Andric // Check Log2LMUL is -3, -2, -1, 0, 1, 2, 3 3981ad6265SDimitry Andric assert(NewLog2LMUL <= 3 && NewLog2LMUL >= -3 && "Bad LMUL number!"); 4081ad6265SDimitry Andric Log2LMUL = NewLog2LMUL; 4181ad6265SDimitry Andric } 4281ad6265SDimitry Andric 4381ad6265SDimitry Andric std::string LMULType::str() const { 4481ad6265SDimitry Andric if (Log2LMUL < 0) 4581ad6265SDimitry Andric return "mf" + utostr(1ULL << (-Log2LMUL)); 4681ad6265SDimitry Andric return "m" + utostr(1ULL << Log2LMUL); 4781ad6265SDimitry Andric } 4881ad6265SDimitry Andric 4981ad6265SDimitry Andric VScaleVal LMULType::getScale(unsigned ElementBitwidth) const { 5081ad6265SDimitry Andric int Log2ScaleResult = 0; 5181ad6265SDimitry Andric switch (ElementBitwidth) { 5281ad6265SDimitry Andric default: 5381ad6265SDimitry Andric break; 5481ad6265SDimitry Andric case 8: 5581ad6265SDimitry Andric Log2ScaleResult = Log2LMUL + 3; 5681ad6265SDimitry Andric break; 5781ad6265SDimitry Andric case 16: 5881ad6265SDimitry Andric Log2ScaleResult = Log2LMUL + 2; 5981ad6265SDimitry Andric break; 6081ad6265SDimitry Andric case 32: 6181ad6265SDimitry Andric Log2ScaleResult = Log2LMUL + 1; 6281ad6265SDimitry Andric break; 6381ad6265SDimitry Andric case 64: 6481ad6265SDimitry Andric Log2ScaleResult = Log2LMUL; 6581ad6265SDimitry Andric break; 6681ad6265SDimitry Andric } 6781ad6265SDimitry Andric // Illegal vscale result would be less than 1 6881ad6265SDimitry Andric if (Log2ScaleResult < 0) 69bdd1243dSDimitry Andric return std::nullopt; 7081ad6265SDimitry Andric return 1 << Log2ScaleResult; 7181ad6265SDimitry Andric } 7281ad6265SDimitry Andric 7381ad6265SDimitry Andric void LMULType::MulLog2LMUL(int log2LMUL) { Log2LMUL += log2LMUL; } 7481ad6265SDimitry Andric 7581ad6265SDimitry Andric RVVType::RVVType(BasicType BT, int Log2LMUL, 7681ad6265SDimitry Andric const PrototypeDescriptor &prototype) 7781ad6265SDimitry Andric : BT(BT), LMUL(LMULType(Log2LMUL)) { 7881ad6265SDimitry Andric applyBasicType(); 7981ad6265SDimitry Andric applyModifier(prototype); 8081ad6265SDimitry Andric Valid = verifyType(); 8181ad6265SDimitry Andric if (Valid) { 8281ad6265SDimitry Andric initBuiltinStr(); 8381ad6265SDimitry Andric initTypeStr(); 8481ad6265SDimitry Andric if (isVector()) { 8581ad6265SDimitry Andric initClangBuiltinStr(); 8681ad6265SDimitry Andric } 8781ad6265SDimitry Andric } 8881ad6265SDimitry Andric } 8981ad6265SDimitry Andric 9081ad6265SDimitry Andric // clang-format off 9181ad6265SDimitry Andric // boolean type are encoded the ratio of n (SEW/LMUL) 9281ad6265SDimitry Andric // SEW/LMUL | 1 | 2 | 4 | 8 | 16 | 32 | 64 9381ad6265SDimitry Andric // c type | vbool64_t | vbool32_t | vbool16_t | vbool8_t | vbool4_t | vbool2_t | vbool1_t 9481ad6265SDimitry Andric // IR type | nxv1i1 | nxv2i1 | nxv4i1 | nxv8i1 | nxv16i1 | nxv32i1 | nxv64i1 9581ad6265SDimitry Andric 9681ad6265SDimitry Andric // type\lmul | 1/8 | 1/4 | 1/2 | 1 | 2 | 4 | 8 9781ad6265SDimitry Andric // -------- |------ | -------- | ------- | ------- | -------- | -------- | -------- 9881ad6265SDimitry Andric // i64 | N/A | N/A | N/A | nxv1i64 | nxv2i64 | nxv4i64 | nxv8i64 9981ad6265SDimitry Andric // i32 | N/A | N/A | nxv1i32 | nxv2i32 | nxv4i32 | nxv8i32 | nxv16i32 10081ad6265SDimitry Andric // i16 | N/A | nxv1i16 | nxv2i16 | nxv4i16 | nxv8i16 | nxv16i16 | nxv32i16 10181ad6265SDimitry Andric // i8 | nxv1i8 | nxv2i8 | nxv4i8 | nxv8i8 | nxv16i8 | nxv32i8 | nxv64i8 10281ad6265SDimitry Andric // double | N/A | N/A | N/A | nxv1f64 | nxv2f64 | nxv4f64 | nxv8f64 10381ad6265SDimitry Andric // float | N/A | N/A | nxv1f32 | nxv2f32 | nxv4f32 | nxv8f32 | nxv16f32 10481ad6265SDimitry Andric // half | N/A | nxv1f16 | nxv2f16 | nxv4f16 | nxv8f16 | nxv16f16 | nxv32f16 10581ad6265SDimitry Andric // clang-format on 10681ad6265SDimitry Andric 10781ad6265SDimitry Andric bool RVVType::verifyType() const { 10881ad6265SDimitry Andric if (ScalarType == Invalid) 10981ad6265SDimitry Andric return false; 11081ad6265SDimitry Andric if (isScalar()) 11181ad6265SDimitry Andric return true; 11281ad6265SDimitry Andric if (!Scale) 11381ad6265SDimitry Andric return false; 11481ad6265SDimitry Andric if (isFloat() && ElementBitwidth == 8) 11581ad6265SDimitry Andric return false; 116bdd1243dSDimitry 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 366bdd1243dSDimitry Andric std::optional<PrototypeDescriptor> 367bdd1243dSDimitry 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!"); 438bdd1243dSDimitry 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]"); 455bdd1243dSDimitry 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!"); 461bdd1243dSDimitry 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"); 478bdd1243dSDimitry 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!"); 484bdd1243dSDimitry 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]"); 510bdd1243dSDimitry 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!"); 516bdd1243dSDimitry 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]"); 542bdd1243dSDimitry 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 788bdd1243dSDimitry Andric std::optional<RVVTypes> 789bdd1243dSDimitry 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) 793bdd1243dSDimitry 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) 799bdd1243dSDimitry Andric return std::nullopt; 80081ad6265SDimitry Andric // Record legal type index 801bdd1243dSDimitry 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 819bdd1243dSDimitry 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)) 828bdd1243dSDimitry 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. 834bdd1243dSDimitry Andric std::pair<std::unordered_map<uint64_t, RVVType>::iterator, bool> 835bdd1243dSDimitry Andric InsertResult = LegalTypes.insert({Idx, T}); 836bdd1243dSDimitry Andric return &(InsertResult.first->second); 83781ad6265SDimitry Andric } 83881ad6265SDimitry Andric // Record illegal type index. 83981ad6265SDimitry Andric IllegalTypes.insert(Idx); 840bdd1243dSDimitry Andric return std::nullopt; 84181ad6265SDimitry Andric } 84281ad6265SDimitry Andric 84381ad6265SDimitry Andric //===----------------------------------------------------------------------===// 84481ad6265SDimitry Andric // RVVIntrinsic implementation 84581ad6265SDimitry Andric //===----------------------------------------------------------------------===// 846bdd1243dSDimitry Andric RVVIntrinsic::RVVIntrinsic(StringRef NewName, StringRef Suffix, 847bdd1243dSDimitry Andric StringRef NewOverloadedName, 848bdd1243dSDimitry Andric StringRef OverloadedSuffix, StringRef IRName, 849bdd1243dSDimitry Andric bool IsMasked, bool HasMaskedOffOperand, bool HasVL, 850bdd1243dSDimitry Andric PolicyScheme Scheme, bool SupportOverloading, 851bdd1243dSDimitry Andric bool HasBuiltinAlias, StringRef ManualCodegen, 852bdd1243dSDimitry Andric const RVVTypes &OutInTypes, 853bdd1243dSDimitry Andric const std::vector<int64_t> &NewIntrinsicTypes, 854bdd1243dSDimitry Andric const std::vector<StringRef> &RequiredFeatures, 855bdd1243dSDimitry Andric unsigned NF, Policy NewPolicyAttrs) 856bdd1243dSDimitry Andric : IRName(IRName), IsMasked(IsMasked), 857bdd1243dSDimitry Andric HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme), 858bdd1243dSDimitry Andric SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias), 859bdd1243dSDimitry 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(); 872bdd1243dSDimitry Andric 873bdd1243dSDimitry Andric updateNamesAndPolicy(IsMasked, hasPolicy(), Name, BuiltinName, OverloadedName, 874bdd1243dSDimitry 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; 883bdd1243dSDimitry 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( 902bdd1243dSDimitry 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) { 906bdd1243dSDimitry 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 912bdd1243dSDimitry Andric llvm::SmallVector<PrototypeDescriptor> RVVIntrinsic::computeBuiltinTypes( 913bdd1243dSDimitry Andric llvm::ArrayRef<PrototypeDescriptor> Prototype, bool IsMasked, 914bdd1243dSDimitry Andric bool HasMaskedOffOperand, bool HasVL, unsigned NF, 915bdd1243dSDimitry Andric PolicyScheme DefaultScheme, Policy PolicyAttrs) { 916972a253aSDimitry Andric SmallVector<PrototypeDescriptor> NewPrototype(Prototype.begin(), 917972a253aSDimitry Andric Prototype.end()); 918bdd1243dSDimitry Andric bool HasPassthruOp = DefaultScheme == PolicyScheme::HasPassthruOperand; 919972a253aSDimitry Andric if (IsMasked) { 920bdd1243dSDimitry Andric // If HasMaskedOffOperand, insert result type as first input operand if 921bdd1243dSDimitry Andric // need. 922bdd1243dSDimitry Andric if (HasMaskedOffOperand && !PolicyAttrs.isTAMAPolicy()) { 923972a253aSDimitry Andric if (NF == 1) { 924972a253aSDimitry Andric NewPrototype.insert(NewPrototype.begin() + 1, NewPrototype[0]); 925bdd1243dSDimitry 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); 932bdd1243dSDimitry 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 } 947bdd1243dSDimitry Andric } else { 948bdd1243dSDimitry Andric if (NF == 1) { 949bdd1243dSDimitry Andric if (PolicyAttrs.isTUPolicy() && HasPassthruOp) 950bdd1243dSDimitry Andric NewPrototype.insert(NewPrototype.begin(), NewPrototype[0]); 951bdd1243dSDimitry Andric } else if (PolicyAttrs.isTUPolicy() && HasPassthruOp) { 952bdd1243dSDimitry Andric // NF > 1 cases for segment load operations. 953bdd1243dSDimitry Andric // Convert 954bdd1243dSDimitry Andric // (void, op0 address, op1 address, ...) 955bdd1243dSDimitry Andric // to 956bdd1243dSDimitry Andric // (void, op0 address, op1 address, maskedoff0, maskedoff1, ...) 957bdd1243dSDimitry Andric PrototypeDescriptor MaskoffType = Prototype[1]; 958bdd1243dSDimitry Andric MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer); 959bdd1243dSDimitry Andric NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType); 960bdd1243dSDimitry 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*1ac55f4cSDimitry Andric llvm::SmallVector<Policy> RVVIntrinsic::getSupportedUnMaskedPolicies() { 970*1ac55f4cSDimitry Andric return {Policy(Policy::PolicyType::Undisturbed)}; // TU 971bdd1243dSDimitry Andric } 972bdd1243dSDimitry Andric 973bdd1243dSDimitry Andric llvm::SmallVector<Policy> 974bdd1243dSDimitry Andric RVVIntrinsic::getSupportedMaskedPolicies(bool HasTailPolicy, 975bdd1243dSDimitry Andric bool HasMaskPolicy) { 976bdd1243dSDimitry Andric if (HasTailPolicy && HasMaskPolicy) 977*1ac55f4cSDimitry Andric return {Policy(Policy::PolicyType::Undisturbed, 978*1ac55f4cSDimitry Andric Policy::PolicyType::Agnostic), // TUM 979*1ac55f4cSDimitry Andric Policy(Policy::PolicyType::Undisturbed, 980*1ac55f4cSDimitry Andric Policy::PolicyType::Undisturbed), // TUMU 981*1ac55f4cSDimitry Andric Policy(Policy::PolicyType::Agnostic, 982*1ac55f4cSDimitry Andric Policy::PolicyType::Undisturbed)}; // MU 983bdd1243dSDimitry Andric if (HasTailPolicy && !HasMaskPolicy) 984bdd1243dSDimitry Andric return {Policy(Policy::PolicyType::Undisturbed, 985*1ac55f4cSDimitry Andric Policy::PolicyType::Agnostic)}; // TU 986bdd1243dSDimitry Andric if (!HasTailPolicy && HasMaskPolicy) 987*1ac55f4cSDimitry Andric return {Policy(Policy::PolicyType::Agnostic, 988*1ac55f4cSDimitry Andric Policy::PolicyType::Undisturbed)}; // MU 989bdd1243dSDimitry Andric llvm_unreachable("An RVV instruction should not be without both tail policy " 990bdd1243dSDimitry Andric "and mask policy"); 991bdd1243dSDimitry Andric } 992bdd1243dSDimitry Andric 993bdd1243dSDimitry Andric void RVVIntrinsic::updateNamesAndPolicy(bool IsMasked, bool HasPolicy, 994bdd1243dSDimitry Andric std::string &Name, 995bdd1243dSDimitry Andric std::string &BuiltinName, 996bdd1243dSDimitry Andric std::string &OverloadedName, 997bdd1243dSDimitry Andric Policy &PolicyAttrs) { 998bdd1243dSDimitry Andric 999bdd1243dSDimitry Andric auto appendPolicySuffix = [&](const std::string &suffix) { 1000bdd1243dSDimitry Andric Name += suffix; 1001bdd1243dSDimitry Andric BuiltinName += suffix; 1002bdd1243dSDimitry Andric OverloadedName += suffix; 1003bdd1243dSDimitry Andric }; 1004bdd1243dSDimitry Andric 1005*1ac55f4cSDimitry Andric // This follows the naming guideline under riscv-c-api-doc to add the 1006*1ac55f4cSDimitry Andric // `__riscv_` suffix for all RVV intrinsics. 1007*1ac55f4cSDimitry Andric Name = "__riscv_" + Name; 1008*1ac55f4cSDimitry Andric OverloadedName = "__riscv_" + OverloadedName; 1009*1ac55f4cSDimitry Andric 1010bdd1243dSDimitry Andric if (IsMasked) { 1011*1ac55f4cSDimitry Andric if (PolicyAttrs.isTUMUPolicy()) 1012*1ac55f4cSDimitry Andric appendPolicySuffix("_tumu"); 1013*1ac55f4cSDimitry Andric else if (PolicyAttrs.isTUMAPolicy()) 1014*1ac55f4cSDimitry Andric appendPolicySuffix("_tum"); 1015*1ac55f4cSDimitry Andric else if (PolicyAttrs.isTAMUPolicy()) 1016*1ac55f4cSDimitry Andric appendPolicySuffix("_mu"); 1017*1ac55f4cSDimitry Andric else if (PolicyAttrs.isTAMAPolicy()) { 1018bdd1243dSDimitry Andric Name += "_m"; 1019bdd1243dSDimitry Andric if (HasPolicy) 1020bdd1243dSDimitry Andric BuiltinName += "_tama"; 1021bdd1243dSDimitry Andric else 1022bdd1243dSDimitry Andric BuiltinName += "_m"; 1023*1ac55f4cSDimitry Andric } else 1024bdd1243dSDimitry Andric llvm_unreachable("Unhandled policy condition"); 1025bdd1243dSDimitry Andric } else { 1026bdd1243dSDimitry Andric if (PolicyAttrs.isTUPolicy()) 1027bdd1243dSDimitry Andric appendPolicySuffix("_tu"); 1028*1ac55f4cSDimitry Andric else if (PolicyAttrs.isTAPolicy()) { 1029*1ac55f4cSDimitry Andric if (HasPolicy) 1030*1ac55f4cSDimitry Andric BuiltinName += "_ta"; 1031*1ac55f4cSDimitry Andric } else 1032bdd1243dSDimitry Andric llvm_unreachable("Unhandled policy condition"); 1033bdd1243dSDimitry Andric } 1034bdd1243dSDimitry Andric } 1035bdd1243dSDimitry Andric 103681ad6265SDimitry Andric SmallVector<PrototypeDescriptor> parsePrototypes(StringRef Prototypes) { 103781ad6265SDimitry Andric SmallVector<PrototypeDescriptor> PrototypeDescriptors; 103881ad6265SDimitry Andric const StringRef Primaries("evwqom0ztul"); 103981ad6265SDimitry Andric while (!Prototypes.empty()) { 104081ad6265SDimitry Andric size_t Idx = 0; 104181ad6265SDimitry Andric // Skip over complex prototype because it could contain primitive type 104281ad6265SDimitry Andric // character. 104381ad6265SDimitry Andric if (Prototypes[0] == '(') 104481ad6265SDimitry Andric Idx = Prototypes.find_first_of(')'); 104581ad6265SDimitry Andric Idx = Prototypes.find_first_of(Primaries, Idx); 104681ad6265SDimitry Andric assert(Idx != StringRef::npos); 104781ad6265SDimitry Andric auto PD = PrototypeDescriptor::parsePrototypeDescriptor( 104881ad6265SDimitry Andric Prototypes.slice(0, Idx + 1)); 104981ad6265SDimitry Andric if (!PD) 105081ad6265SDimitry Andric llvm_unreachable("Error during parsing prototype."); 105181ad6265SDimitry Andric PrototypeDescriptors.push_back(*PD); 105281ad6265SDimitry Andric Prototypes = Prototypes.drop_front(Idx + 1); 105381ad6265SDimitry Andric } 105481ad6265SDimitry Andric return PrototypeDescriptors; 105581ad6265SDimitry Andric } 105681ad6265SDimitry Andric 1057972a253aSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const RVVIntrinsicRecord &Record) { 1058972a253aSDimitry Andric OS << "{"; 1059972a253aSDimitry Andric OS << "\"" << Record.Name << "\","; 1060972a253aSDimitry Andric if (Record.OverloadedName == nullptr || 1061972a253aSDimitry Andric StringRef(Record.OverloadedName).empty()) 1062972a253aSDimitry Andric OS << "nullptr,"; 1063972a253aSDimitry Andric else 1064972a253aSDimitry Andric OS << "\"" << Record.OverloadedName << "\","; 1065972a253aSDimitry Andric OS << Record.PrototypeIndex << ","; 1066972a253aSDimitry Andric OS << Record.SuffixIndex << ","; 1067972a253aSDimitry Andric OS << Record.OverloadedSuffixIndex << ","; 1068972a253aSDimitry Andric OS << (int)Record.PrototypeLength << ","; 1069972a253aSDimitry Andric OS << (int)Record.SuffixLength << ","; 1070972a253aSDimitry Andric OS << (int)Record.OverloadedSuffixSize << ","; 1071972a253aSDimitry Andric OS << (int)Record.RequiredExtensions << ","; 1072972a253aSDimitry Andric OS << (int)Record.TypeRangeMask << ","; 1073972a253aSDimitry Andric OS << (int)Record.Log2LMULMask << ","; 1074972a253aSDimitry Andric OS << (int)Record.NF << ","; 1075972a253aSDimitry Andric OS << (int)Record.HasMasked << ","; 1076972a253aSDimitry Andric OS << (int)Record.HasVL << ","; 1077972a253aSDimitry Andric OS << (int)Record.HasMaskedOffOperand << ","; 1078bdd1243dSDimitry Andric OS << (int)Record.HasTailPolicy << ","; 1079bdd1243dSDimitry Andric OS << (int)Record.HasMaskPolicy << ","; 1080bdd1243dSDimitry Andric OS << (int)Record.UnMaskedPolicyScheme << ","; 1081bdd1243dSDimitry Andric OS << (int)Record.MaskedPolicyScheme << ","; 1082972a253aSDimitry Andric OS << "},\n"; 1083972a253aSDimitry Andric return OS; 1084972a253aSDimitry Andric } 1085972a253aSDimitry Andric 108681ad6265SDimitry Andric } // end namespace RISCV 108781ad6265SDimitry Andric } // end namespace clang 1088