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