1f26c41e8SKito Cheng //===- RISCVVIntrinsicUtils.cpp - RISC-V Vector Intrinsic Utils -*- C++ -*-===// 2f26c41e8SKito Cheng // 3f26c41e8SKito Cheng // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4f26c41e8SKito Cheng // See https://llvm.org/LICENSE.txt for license information. 5f26c41e8SKito Cheng // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6f26c41e8SKito Cheng // 7f26c41e8SKito Cheng //===----------------------------------------------------------------------===// 8f26c41e8SKito Cheng 9f26c41e8SKito Cheng #include "clang/Support/RISCVVIntrinsicUtils.h" 10f26c41e8SKito Cheng #include "llvm/ADT/ArrayRef.h" 11f26c41e8SKito Cheng #include "llvm/ADT/SmallSet.h" 12f26c41e8SKito Cheng #include "llvm/ADT/StringExtras.h" 13f26c41e8SKito Cheng #include "llvm/ADT/StringSet.h" 14f26c41e8SKito Cheng #include "llvm/ADT/Twine.h" 1506380284SeopXD #include "llvm/Support/ErrorHandling.h" 16f26c41e8SKito Cheng #include "llvm/Support/raw_ostream.h" 17f26c41e8SKito Cheng #include <numeric> 189cf4419eSKazu Hirata #include <optional> 19f26c41e8SKito Cheng 20f26c41e8SKito Cheng using namespace llvm; 21f26c41e8SKito Cheng 22f26c41e8SKito Cheng namespace clang { 23f26c41e8SKito Cheng namespace RISCV { 24f26c41e8SKito Cheng 257ff0bf57SKito Cheng const PrototypeDescriptor PrototypeDescriptor::Mask = PrototypeDescriptor( 267ff0bf57SKito Cheng BaseTypeModifier::Vector, VectorTypeModifier::MaskVector); 277ff0bf57SKito Cheng const PrototypeDescriptor PrototypeDescriptor::VL = 287ff0bf57SKito Cheng PrototypeDescriptor(BaseTypeModifier::SizeT); 297ff0bf57SKito Cheng const PrototypeDescriptor PrototypeDescriptor::Vector = 307ff0bf57SKito Cheng PrototypeDescriptor(BaseTypeModifier::Vector); 317ff0bf57SKito Cheng 32f26c41e8SKito Cheng //===----------------------------------------------------------------------===// 33f26c41e8SKito Cheng // Type implementation 34f26c41e8SKito Cheng //===----------------------------------------------------------------------===// 35f26c41e8SKito Cheng 36f26c41e8SKito Cheng LMULType::LMULType(int NewLog2LMUL) { 37f26c41e8SKito Cheng // Check Log2LMUL is -3, -2, -1, 0, 1, 2, 3 38f26c41e8SKito Cheng assert(NewLog2LMUL <= 3 && NewLog2LMUL >= -3 && "Bad LMUL number!"); 39f26c41e8SKito Cheng Log2LMUL = NewLog2LMUL; 40f26c41e8SKito Cheng } 41f26c41e8SKito Cheng 42f26c41e8SKito Cheng std::string LMULType::str() const { 43f26c41e8SKito Cheng if (Log2LMUL < 0) 44f26c41e8SKito Cheng return "mf" + utostr(1ULL << (-Log2LMUL)); 45f26c41e8SKito Cheng return "m" + utostr(1ULL << Log2LMUL); 46f26c41e8SKito Cheng } 47f26c41e8SKito Cheng 48f26c41e8SKito Cheng VScaleVal LMULType::getScale(unsigned ElementBitwidth) const { 49f26c41e8SKito Cheng int Log2ScaleResult = 0; 50f26c41e8SKito Cheng switch (ElementBitwidth) { 51f26c41e8SKito Cheng default: 52f26c41e8SKito Cheng break; 53f26c41e8SKito Cheng case 8: 54f26c41e8SKito Cheng Log2ScaleResult = Log2LMUL + 3; 55f26c41e8SKito Cheng break; 56f26c41e8SKito Cheng case 16: 57f26c41e8SKito Cheng Log2ScaleResult = Log2LMUL + 2; 58f26c41e8SKito Cheng break; 59f26c41e8SKito Cheng case 32: 60f26c41e8SKito Cheng Log2ScaleResult = Log2LMUL + 1; 61f26c41e8SKito Cheng break; 62f26c41e8SKito Cheng case 64: 63f26c41e8SKito Cheng Log2ScaleResult = Log2LMUL; 64f26c41e8SKito Cheng break; 65f26c41e8SKito Cheng } 66f26c41e8SKito Cheng // Illegal vscale result would be less than 1 67f26c41e8SKito Cheng if (Log2ScaleResult < 0) 685891420eSKazu Hirata return std::nullopt; 69f26c41e8SKito Cheng return 1 << Log2ScaleResult; 70f26c41e8SKito Cheng } 71f26c41e8SKito Cheng 72f26c41e8SKito Cheng void LMULType::MulLog2LMUL(int log2LMUL) { Log2LMUL += log2LMUL; } 73f26c41e8SKito Cheng 747ff0bf57SKito Cheng RVVType::RVVType(BasicType BT, int Log2LMUL, 757ff0bf57SKito Cheng const PrototypeDescriptor &prototype) 76f26c41e8SKito Cheng : BT(BT), LMUL(LMULType(Log2LMUL)) { 77f26c41e8SKito Cheng applyBasicType(); 78f26c41e8SKito Cheng applyModifier(prototype); 79f26c41e8SKito Cheng Valid = verifyType(); 80f26c41e8SKito Cheng if (Valid) { 81f26c41e8SKito Cheng initBuiltinStr(); 82f26c41e8SKito Cheng initTypeStr(); 83f26c41e8SKito Cheng if (isVector()) { 84f26c41e8SKito Cheng initClangBuiltinStr(); 85f26c41e8SKito Cheng } 86f26c41e8SKito Cheng } 87f26c41e8SKito Cheng } 88f26c41e8SKito Cheng 89f26c41e8SKito Cheng // clang-format off 90f26c41e8SKito Cheng // boolean type are encoded the ratio of n (SEW/LMUL) 91f26c41e8SKito Cheng // SEW/LMUL | 1 | 2 | 4 | 8 | 16 | 32 | 64 92f26c41e8SKito Cheng // c type | vbool64_t | vbool32_t | vbool16_t | vbool8_t | vbool4_t | vbool2_t | vbool1_t 93f26c41e8SKito Cheng // IR type | nxv1i1 | nxv2i1 | nxv4i1 | nxv8i1 | nxv16i1 | nxv32i1 | nxv64i1 94f26c41e8SKito Cheng 95f26c41e8SKito Cheng // type\lmul | 1/8 | 1/4 | 1/2 | 1 | 2 | 4 | 8 96f26c41e8SKito Cheng // -------- |------ | -------- | ------- | ------- | -------- | -------- | -------- 97f26c41e8SKito Cheng // i64 | N/A | N/A | N/A | nxv1i64 | nxv2i64 | nxv4i64 | nxv8i64 98f26c41e8SKito Cheng // i32 | N/A | N/A | nxv1i32 | nxv2i32 | nxv4i32 | nxv8i32 | nxv16i32 99f26c41e8SKito Cheng // i16 | N/A | nxv1i16 | nxv2i16 | nxv4i16 | nxv8i16 | nxv16i16 | nxv32i16 100f26c41e8SKito Cheng // i8 | nxv1i8 | nxv2i8 | nxv4i8 | nxv8i8 | nxv16i8 | nxv32i8 | nxv64i8 101f26c41e8SKito Cheng // double | N/A | N/A | N/A | nxv1f64 | nxv2f64 | nxv4f64 | nxv8f64 102f26c41e8SKito Cheng // float | N/A | N/A | nxv1f32 | nxv2f32 | nxv4f32 | nxv8f32 | nxv16f32 103f26c41e8SKito Cheng // half | N/A | nxv1f16 | nxv2f16 | nxv4f16 | nxv8f16 | nxv16f16 | nxv32f16 104fbdf6e27SShao-Ce SUN // bfloat16 | N/A | nxv1bf16 | nxv2bf16| nxv4bf16| nxv8bf16 | nxv16bf16| nxv32bf16 105f26c41e8SKito Cheng // clang-format on 106f26c41e8SKito Cheng 107f26c41e8SKito Cheng bool RVVType::verifyType() const { 108f26c41e8SKito Cheng if (ScalarType == Invalid) 109f26c41e8SKito Cheng return false; 110f26c41e8SKito Cheng if (isScalar()) 111f26c41e8SKito Cheng return true; 11297afce08SKazu Hirata if (!Scale) 113f26c41e8SKito Cheng return false; 114f26c41e8SKito Cheng if (isFloat() && ElementBitwidth == 8) 115f26c41e8SKito Cheng return false; 116fbdf6e27SShao-Ce SUN if (isBFloat() && ElementBitwidth != 16) 117fbdf6e27SShao-Ce SUN return false; 1180019226cSeopXD if (IsTuple && (NF == 1 || NF > 8)) 1190019226cSeopXD return false; 1205847ec4dSeopXD if (IsTuple && (1 << std::max(0, LMUL.Log2LMUL)) * NF > 8) 1215847ec4dSeopXD return false; 122f4b90773SFangrui Song unsigned V = *Scale; 123f26c41e8SKito Cheng switch (ElementBitwidth) { 124f26c41e8SKito Cheng case 1: 125f26c41e8SKito Cheng case 8: 126f26c41e8SKito Cheng // Check Scale is 1,2,4,8,16,32,64 127f26c41e8SKito Cheng return (V <= 64 && isPowerOf2_32(V)); 128f26c41e8SKito Cheng case 16: 129f26c41e8SKito Cheng // Check Scale is 1,2,4,8,16,32 130f26c41e8SKito Cheng return (V <= 32 && isPowerOf2_32(V)); 131f26c41e8SKito Cheng case 32: 132f26c41e8SKito Cheng // Check Scale is 1,2,4,8,16 133f26c41e8SKito Cheng return (V <= 16 && isPowerOf2_32(V)); 134f26c41e8SKito Cheng case 64: 135f26c41e8SKito Cheng // Check Scale is 1,2,4,8 136f26c41e8SKito Cheng return (V <= 8 && isPowerOf2_32(V)); 137f26c41e8SKito Cheng } 138f26c41e8SKito Cheng return false; 139f26c41e8SKito Cheng } 140f26c41e8SKito Cheng 141f26c41e8SKito Cheng void RVVType::initBuiltinStr() { 142f26c41e8SKito Cheng assert(isValid() && "RVVType is invalid"); 143f26c41e8SKito Cheng switch (ScalarType) { 144f26c41e8SKito Cheng case ScalarTypeKind::Void: 145f26c41e8SKito Cheng BuiltinStr = "v"; 146f26c41e8SKito Cheng return; 147f26c41e8SKito Cheng case ScalarTypeKind::Size_t: 148f26c41e8SKito Cheng BuiltinStr = "z"; 149f26c41e8SKito Cheng if (IsImmediate) 150f26c41e8SKito Cheng BuiltinStr = "I" + BuiltinStr; 151f26c41e8SKito Cheng if (IsPointer) 152f26c41e8SKito Cheng BuiltinStr += "*"; 153f26c41e8SKito Cheng return; 154f26c41e8SKito Cheng case ScalarTypeKind::Ptrdiff_t: 155f26c41e8SKito Cheng BuiltinStr = "Y"; 156f26c41e8SKito Cheng return; 157f26c41e8SKito Cheng case ScalarTypeKind::UnsignedLong: 158f26c41e8SKito Cheng BuiltinStr = "ULi"; 159f26c41e8SKito Cheng return; 160f26c41e8SKito Cheng case ScalarTypeKind::SignedLong: 161f26c41e8SKito Cheng BuiltinStr = "Li"; 162f26c41e8SKito Cheng return; 163f26c41e8SKito Cheng case ScalarTypeKind::Boolean: 164f26c41e8SKito Cheng assert(ElementBitwidth == 1); 165f26c41e8SKito Cheng BuiltinStr += "b"; 166f26c41e8SKito Cheng break; 167f26c41e8SKito Cheng case ScalarTypeKind::SignedInteger: 168f26c41e8SKito Cheng case ScalarTypeKind::UnsignedInteger: 169f26c41e8SKito Cheng switch (ElementBitwidth) { 170f26c41e8SKito Cheng case 8: 171f26c41e8SKito Cheng BuiltinStr += "c"; 172f26c41e8SKito Cheng break; 173f26c41e8SKito Cheng case 16: 174f26c41e8SKito Cheng BuiltinStr += "s"; 175f26c41e8SKito Cheng break; 176f26c41e8SKito Cheng case 32: 177f26c41e8SKito Cheng BuiltinStr += "i"; 178f26c41e8SKito Cheng break; 179f26c41e8SKito Cheng case 64: 180f26c41e8SKito Cheng BuiltinStr += "Wi"; 181f26c41e8SKito Cheng break; 182f26c41e8SKito Cheng default: 183f26c41e8SKito Cheng llvm_unreachable("Unhandled ElementBitwidth!"); 184f26c41e8SKito Cheng } 185f26c41e8SKito Cheng if (isSignedInteger()) 186f26c41e8SKito Cheng BuiltinStr = "S" + BuiltinStr; 187f26c41e8SKito Cheng else 188f26c41e8SKito Cheng BuiltinStr = "U" + BuiltinStr; 189f26c41e8SKito Cheng break; 190f26c41e8SKito Cheng case ScalarTypeKind::Float: 191f26c41e8SKito Cheng switch (ElementBitwidth) { 192f26c41e8SKito Cheng case 16: 193f26c41e8SKito Cheng BuiltinStr += "x"; 194f26c41e8SKito Cheng break; 195f26c41e8SKito Cheng case 32: 196f26c41e8SKito Cheng BuiltinStr += "f"; 197f26c41e8SKito Cheng break; 198f26c41e8SKito Cheng case 64: 199f26c41e8SKito Cheng BuiltinStr += "d"; 200f26c41e8SKito Cheng break; 201f26c41e8SKito Cheng default: 202f26c41e8SKito Cheng llvm_unreachable("Unhandled ElementBitwidth!"); 203f26c41e8SKito Cheng } 204f26c41e8SKito Cheng break; 205fbdf6e27SShao-Ce SUN case ScalarTypeKind::BFloat: 206fa8347fbSMichael Maitland BuiltinStr += "y"; 207fbdf6e27SShao-Ce SUN break; 208f26c41e8SKito Cheng default: 209f26c41e8SKito Cheng llvm_unreachable("ScalarType is invalid!"); 210f26c41e8SKito Cheng } 211f26c41e8SKito Cheng if (IsImmediate) 212f26c41e8SKito Cheng BuiltinStr = "I" + BuiltinStr; 213f26c41e8SKito Cheng if (isScalar()) { 214f26c41e8SKito Cheng if (IsConstant) 215f26c41e8SKito Cheng BuiltinStr += "C"; 216f26c41e8SKito Cheng if (IsPointer) 217f26c41e8SKito Cheng BuiltinStr += "*"; 218f26c41e8SKito Cheng return; 219f26c41e8SKito Cheng } 220ca4af13eSKazu Hirata BuiltinStr = "q" + utostr(*Scale) + BuiltinStr; 221f26c41e8SKito Cheng // Pointer to vector types. Defined for segment load intrinsics. 222f26c41e8SKito Cheng // segment load intrinsics have pointer type arguments to store the loaded 223f26c41e8SKito Cheng // vector values. 224f26c41e8SKito Cheng if (IsPointer) 225f26c41e8SKito Cheng BuiltinStr += "*"; 2260019226cSeopXD 2270019226cSeopXD if (IsTuple) 2280019226cSeopXD BuiltinStr = "T" + utostr(NF) + BuiltinStr; 229f26c41e8SKito Cheng } 230f26c41e8SKito Cheng 231f26c41e8SKito Cheng void RVVType::initClangBuiltinStr() { 232f26c41e8SKito Cheng assert(isValid() && "RVVType is invalid"); 233f26c41e8SKito Cheng assert(isVector() && "Handle Vector type only"); 234f26c41e8SKito Cheng 235f26c41e8SKito Cheng ClangBuiltinStr = "__rvv_"; 236f26c41e8SKito Cheng switch (ScalarType) { 237f26c41e8SKito Cheng case ScalarTypeKind::Boolean: 238ca4af13eSKazu Hirata ClangBuiltinStr += "bool" + utostr(64 / *Scale) + "_t"; 239f26c41e8SKito Cheng return; 240f26c41e8SKito Cheng case ScalarTypeKind::Float: 241f26c41e8SKito Cheng ClangBuiltinStr += "float"; 242f26c41e8SKito Cheng break; 243fbdf6e27SShao-Ce SUN case ScalarTypeKind::BFloat: 244fbdf6e27SShao-Ce SUN ClangBuiltinStr += "bfloat"; 245fbdf6e27SShao-Ce SUN break; 246f26c41e8SKito Cheng case ScalarTypeKind::SignedInteger: 247f26c41e8SKito Cheng ClangBuiltinStr += "int"; 248f26c41e8SKito Cheng break; 249f26c41e8SKito Cheng case ScalarTypeKind::UnsignedInteger: 250f26c41e8SKito Cheng ClangBuiltinStr += "uint"; 251f26c41e8SKito Cheng break; 252f26c41e8SKito Cheng default: 253f26c41e8SKito Cheng llvm_unreachable("ScalarTypeKind is invalid"); 254f26c41e8SKito Cheng } 2550019226cSeopXD ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.str() + 2560019226cSeopXD (IsTuple ? "x" + utostr(NF) : "") + "_t"; 257f26c41e8SKito Cheng } 258f26c41e8SKito Cheng 259f26c41e8SKito Cheng void RVVType::initTypeStr() { 260f26c41e8SKito Cheng assert(isValid() && "RVVType is invalid"); 261f26c41e8SKito Cheng 262f26c41e8SKito Cheng if (IsConstant) 263f26c41e8SKito Cheng Str += "const "; 264f26c41e8SKito Cheng 265f26c41e8SKito Cheng auto getTypeString = [&](StringRef TypeStr) { 266f26c41e8SKito Cheng if (isScalar()) 267f26c41e8SKito Cheng return Twine(TypeStr + Twine(ElementBitwidth) + "_t").str(); 2680019226cSeopXD return Twine("v" + TypeStr + Twine(ElementBitwidth) + LMUL.str() + 2690019226cSeopXD (IsTuple ? "x" + utostr(NF) : "") + "_t") 270f26c41e8SKito Cheng .str(); 271f26c41e8SKito Cheng }; 272f26c41e8SKito Cheng 273f26c41e8SKito Cheng switch (ScalarType) { 274f26c41e8SKito Cheng case ScalarTypeKind::Void: 275f26c41e8SKito Cheng Str = "void"; 276f26c41e8SKito Cheng return; 277f26c41e8SKito Cheng case ScalarTypeKind::Size_t: 278f26c41e8SKito Cheng Str = "size_t"; 279f26c41e8SKito Cheng if (IsPointer) 280f26c41e8SKito Cheng Str += " *"; 281f26c41e8SKito Cheng return; 282f26c41e8SKito Cheng case ScalarTypeKind::Ptrdiff_t: 283f26c41e8SKito Cheng Str = "ptrdiff_t"; 284f26c41e8SKito Cheng return; 285f26c41e8SKito Cheng case ScalarTypeKind::UnsignedLong: 286f26c41e8SKito Cheng Str = "unsigned long"; 287f26c41e8SKito Cheng return; 288f26c41e8SKito Cheng case ScalarTypeKind::SignedLong: 289f26c41e8SKito Cheng Str = "long"; 290f26c41e8SKito Cheng return; 291f26c41e8SKito Cheng case ScalarTypeKind::Boolean: 292f26c41e8SKito Cheng if (isScalar()) 293f26c41e8SKito Cheng Str += "bool"; 294f26c41e8SKito Cheng else 295f26c41e8SKito Cheng // Vector bool is special case, the formulate is 296f26c41e8SKito Cheng // `vbool<N>_t = MVT::nxv<64/N>i1` ex. vbool16_t = MVT::4i1 297ca4af13eSKazu Hirata Str += "vbool" + utostr(64 / *Scale) + "_t"; 298f26c41e8SKito Cheng break; 299f26c41e8SKito Cheng case ScalarTypeKind::Float: 300f26c41e8SKito Cheng if (isScalar()) { 301f26c41e8SKito Cheng if (ElementBitwidth == 64) 302f26c41e8SKito Cheng Str += "double"; 303f26c41e8SKito Cheng else if (ElementBitwidth == 32) 304f26c41e8SKito Cheng Str += "float"; 305f26c41e8SKito Cheng else if (ElementBitwidth == 16) 306f26c41e8SKito Cheng Str += "_Float16"; 307f26c41e8SKito Cheng else 308f26c41e8SKito Cheng llvm_unreachable("Unhandled floating type."); 309f26c41e8SKito Cheng } else 310f26c41e8SKito Cheng Str += getTypeString("float"); 311f26c41e8SKito Cheng break; 312fbdf6e27SShao-Ce SUN case ScalarTypeKind::BFloat: 313fbdf6e27SShao-Ce SUN if (isScalar()) { 314fbdf6e27SShao-Ce SUN if (ElementBitwidth == 16) 315fbdf6e27SShao-Ce SUN Str += "__bf16"; 316fbdf6e27SShao-Ce SUN else 317fbdf6e27SShao-Ce SUN llvm_unreachable("Unhandled floating type."); 318fbdf6e27SShao-Ce SUN } else 319fbdf6e27SShao-Ce SUN Str += getTypeString("bfloat"); 320fbdf6e27SShao-Ce SUN break; 321f26c41e8SKito Cheng case ScalarTypeKind::SignedInteger: 322f26c41e8SKito Cheng Str += getTypeString("int"); 323f26c41e8SKito Cheng break; 324f26c41e8SKito Cheng case ScalarTypeKind::UnsignedInteger: 325f26c41e8SKito Cheng Str += getTypeString("uint"); 326f26c41e8SKito Cheng break; 327f26c41e8SKito Cheng default: 328f26c41e8SKito Cheng llvm_unreachable("ScalarType is invalid!"); 329f26c41e8SKito Cheng } 330f26c41e8SKito Cheng if (IsPointer) 331f26c41e8SKito Cheng Str += " *"; 332f26c41e8SKito Cheng } 333f26c41e8SKito Cheng 334f26c41e8SKito Cheng void RVVType::initShortStr() { 335f26c41e8SKito Cheng switch (ScalarType) { 336f26c41e8SKito Cheng case ScalarTypeKind::Boolean: 337f26c41e8SKito Cheng assert(isVector()); 338ca4af13eSKazu Hirata ShortStr = "b" + utostr(64 / *Scale); 339f26c41e8SKito Cheng return; 340f26c41e8SKito Cheng case ScalarTypeKind::Float: 341f26c41e8SKito Cheng ShortStr = "f" + utostr(ElementBitwidth); 342f26c41e8SKito Cheng break; 343fbdf6e27SShao-Ce SUN case ScalarTypeKind::BFloat: 344fbdf6e27SShao-Ce SUN ShortStr = "bf" + utostr(ElementBitwidth); 345fbdf6e27SShao-Ce SUN break; 346f26c41e8SKito Cheng case ScalarTypeKind::SignedInteger: 347f26c41e8SKito Cheng ShortStr = "i" + utostr(ElementBitwidth); 348f26c41e8SKito Cheng break; 349f26c41e8SKito Cheng case ScalarTypeKind::UnsignedInteger: 350f26c41e8SKito Cheng ShortStr = "u" + utostr(ElementBitwidth); 351f26c41e8SKito Cheng break; 352f26c41e8SKito Cheng default: 353f26c41e8SKito Cheng llvm_unreachable("Unhandled case!"); 354f26c41e8SKito Cheng } 355f26c41e8SKito Cheng if (isVector()) 356f26c41e8SKito Cheng ShortStr += LMUL.str(); 3576a097e27SeopXD if (isTuple()) 3586a097e27SeopXD ShortStr += "x" + utostr(NF); 359f26c41e8SKito Cheng } 360f26c41e8SKito Cheng 3610e9548bbSeopXD static VectorTypeModifier getTupleVTM(unsigned NF) { 3620e9548bbSeopXD assert(2 <= NF && NF <= 8 && "2 <= NF <= 8"); 3630e9548bbSeopXD return static_cast<VectorTypeModifier>( 3640e9548bbSeopXD static_cast<uint8_t>(VectorTypeModifier::Tuple2) + (NF - 2)); 3650e9548bbSeopXD } 3660e9548bbSeopXD 367f26c41e8SKito Cheng void RVVType::applyBasicType() { 368f26c41e8SKito Cheng switch (BT) { 3697ff0bf57SKito Cheng case BasicType::Int8: 370f26c41e8SKito Cheng ElementBitwidth = 8; 371f26c41e8SKito Cheng ScalarType = ScalarTypeKind::SignedInteger; 372f26c41e8SKito Cheng break; 3737ff0bf57SKito Cheng case BasicType::Int16: 374f26c41e8SKito Cheng ElementBitwidth = 16; 375f26c41e8SKito Cheng ScalarType = ScalarTypeKind::SignedInteger; 376f26c41e8SKito Cheng break; 3777ff0bf57SKito Cheng case BasicType::Int32: 378f26c41e8SKito Cheng ElementBitwidth = 32; 379f26c41e8SKito Cheng ScalarType = ScalarTypeKind::SignedInteger; 380f26c41e8SKito Cheng break; 3817ff0bf57SKito Cheng case BasicType::Int64: 382f26c41e8SKito Cheng ElementBitwidth = 64; 383f26c41e8SKito Cheng ScalarType = ScalarTypeKind::SignedInteger; 384f26c41e8SKito Cheng break; 3857ff0bf57SKito Cheng case BasicType::Float16: 386f26c41e8SKito Cheng ElementBitwidth = 16; 387f26c41e8SKito Cheng ScalarType = ScalarTypeKind::Float; 388f26c41e8SKito Cheng break; 3897ff0bf57SKito Cheng case BasicType::Float32: 390f26c41e8SKito Cheng ElementBitwidth = 32; 391f26c41e8SKito Cheng ScalarType = ScalarTypeKind::Float; 392f26c41e8SKito Cheng break; 3937ff0bf57SKito Cheng case BasicType::Float64: 394f26c41e8SKito Cheng ElementBitwidth = 64; 395f26c41e8SKito Cheng ScalarType = ScalarTypeKind::Float; 396f26c41e8SKito Cheng break; 397fbdf6e27SShao-Ce SUN case BasicType::BFloat16: 398fbdf6e27SShao-Ce SUN ElementBitwidth = 16; 399fbdf6e27SShao-Ce SUN ScalarType = ScalarTypeKind::BFloat; 400fbdf6e27SShao-Ce SUN break; 401f26c41e8SKito Cheng default: 402f26c41e8SKito Cheng llvm_unreachable("Unhandled type code!"); 403f26c41e8SKito Cheng } 404f26c41e8SKito Cheng assert(ElementBitwidth != 0 && "Bad element bitwidth!"); 405f26c41e8SKito Cheng } 406f26c41e8SKito Cheng 4079cf4419eSKazu Hirata std::optional<PrototypeDescriptor> 4089cf4419eSKazu Hirata PrototypeDescriptor::parsePrototypeDescriptor( 4097ff0bf57SKito Cheng llvm::StringRef PrototypeDescriptorStr) { 4107ff0bf57SKito Cheng PrototypeDescriptor PD; 4117ff0bf57SKito Cheng BaseTypeModifier PT = BaseTypeModifier::Invalid; 4127ff0bf57SKito Cheng VectorTypeModifier VTM = VectorTypeModifier::NoModifier; 4137ff0bf57SKito Cheng 4147ff0bf57SKito Cheng if (PrototypeDescriptorStr.empty()) 4157ff0bf57SKito Cheng return PD; 4167ff0bf57SKito Cheng 4177ff0bf57SKito Cheng // Handle base type modifier 4187ff0bf57SKito Cheng auto PType = PrototypeDescriptorStr.back(); 419f26c41e8SKito Cheng switch (PType) { 420f26c41e8SKito Cheng case 'e': 4217ff0bf57SKito Cheng PT = BaseTypeModifier::Scalar; 422f26c41e8SKito Cheng break; 423f26c41e8SKito Cheng case 'v': 4247ff0bf57SKito Cheng PT = BaseTypeModifier::Vector; 425f26c41e8SKito Cheng break; 426f26c41e8SKito Cheng case 'w': 4277ff0bf57SKito Cheng PT = BaseTypeModifier::Vector; 4287ff0bf57SKito Cheng VTM = VectorTypeModifier::Widening2XVector; 429f26c41e8SKito Cheng break; 430f26c41e8SKito Cheng case 'q': 4317ff0bf57SKito Cheng PT = BaseTypeModifier::Vector; 4327ff0bf57SKito Cheng VTM = VectorTypeModifier::Widening4XVector; 433f26c41e8SKito Cheng break; 434f26c41e8SKito Cheng case 'o': 4357ff0bf57SKito Cheng PT = BaseTypeModifier::Vector; 4367ff0bf57SKito Cheng VTM = VectorTypeModifier::Widening8XVector; 437f26c41e8SKito Cheng break; 438f26c41e8SKito Cheng case 'm': 4397ff0bf57SKito Cheng PT = BaseTypeModifier::Vector; 4407ff0bf57SKito Cheng VTM = VectorTypeModifier::MaskVector; 441f26c41e8SKito Cheng break; 442f26c41e8SKito Cheng case '0': 4437ff0bf57SKito Cheng PT = BaseTypeModifier::Void; 444f26c41e8SKito Cheng break; 445f26c41e8SKito Cheng case 'z': 4467ff0bf57SKito Cheng PT = BaseTypeModifier::SizeT; 447f26c41e8SKito Cheng break; 448f26c41e8SKito Cheng case 't': 4497ff0bf57SKito Cheng PT = BaseTypeModifier::Ptrdiff; 450f26c41e8SKito Cheng break; 451f26c41e8SKito Cheng case 'u': 4527ff0bf57SKito Cheng PT = BaseTypeModifier::UnsignedLong; 453f26c41e8SKito Cheng break; 454f26c41e8SKito Cheng case 'l': 4557ff0bf57SKito Cheng PT = BaseTypeModifier::SignedLong; 456f26c41e8SKito Cheng break; 45774f38df1SBrandon Wu case 'f': 45874f38df1SBrandon Wu PT = BaseTypeModifier::Float32; 45974f38df1SBrandon Wu break; 460f26c41e8SKito Cheng default: 461f26c41e8SKito Cheng llvm_unreachable("Illegal primitive type transformers!"); 462f26c41e8SKito Cheng } 4637ff0bf57SKito Cheng PD.PT = static_cast<uint8_t>(PT); 4647ff0bf57SKito Cheng PrototypeDescriptorStr = PrototypeDescriptorStr.drop_back(); 465f26c41e8SKito Cheng 4667ff0bf57SKito Cheng // Compute the vector type transformers, it can only appear one time. 467f3dcc235SKazu Hirata if (PrototypeDescriptorStr.starts_with("(")) { 4687ff0bf57SKito Cheng assert(VTM == VectorTypeModifier::NoModifier && 4697ff0bf57SKito Cheng "VectorTypeModifier should only have one modifier"); 4707ff0bf57SKito Cheng size_t Idx = PrototypeDescriptorStr.find(')'); 471f26c41e8SKito Cheng assert(Idx != StringRef::npos); 4727ff0bf57SKito Cheng StringRef ComplexType = PrototypeDescriptorStr.slice(1, Idx); 4737ff0bf57SKito Cheng PrototypeDescriptorStr = PrototypeDescriptorStr.drop_front(Idx + 1); 4747ff0bf57SKito Cheng assert(!PrototypeDescriptorStr.contains('(') && 4757ff0bf57SKito Cheng "Only allow one vector type modifier"); 476f26c41e8SKito Cheng 477f26c41e8SKito Cheng auto ComplexTT = ComplexType.split(":"); 478f26c41e8SKito Cheng if (ComplexTT.first == "Log2EEW") { 479f26c41e8SKito Cheng uint32_t Log2EEW; 4807ff0bf57SKito Cheng if (ComplexTT.second.getAsInteger(10, Log2EEW)) { 4817ff0bf57SKito Cheng llvm_unreachable("Invalid Log2EEW value!"); 4825891420eSKazu Hirata return std::nullopt; 4837ff0bf57SKito Cheng } 4847ff0bf57SKito Cheng switch (Log2EEW) { 4857ff0bf57SKito Cheng case 3: 4867ff0bf57SKito Cheng VTM = VectorTypeModifier::Log2EEW3; 4877ff0bf57SKito Cheng break; 4887ff0bf57SKito Cheng case 4: 4897ff0bf57SKito Cheng VTM = VectorTypeModifier::Log2EEW4; 4907ff0bf57SKito Cheng break; 4917ff0bf57SKito Cheng case 5: 4927ff0bf57SKito Cheng VTM = VectorTypeModifier::Log2EEW5; 4937ff0bf57SKito Cheng break; 4947ff0bf57SKito Cheng case 6: 4957ff0bf57SKito Cheng VTM = VectorTypeModifier::Log2EEW6; 4967ff0bf57SKito Cheng break; 4977ff0bf57SKito Cheng default: 4987ff0bf57SKito Cheng llvm_unreachable("Invalid Log2EEW value, should be [3-6]"); 4995891420eSKazu Hirata return std::nullopt; 5007ff0bf57SKito Cheng } 501f26c41e8SKito Cheng } else if (ComplexTT.first == "FixedSEW") { 502f26c41e8SKito Cheng uint32_t NewSEW; 5037ff0bf57SKito Cheng if (ComplexTT.second.getAsInteger(10, NewSEW)) { 5047ff0bf57SKito Cheng llvm_unreachable("Invalid FixedSEW value!"); 5055891420eSKazu Hirata return std::nullopt; 506f26c41e8SKito Cheng } 5077ff0bf57SKito Cheng switch (NewSEW) { 5087ff0bf57SKito Cheng case 8: 5097ff0bf57SKito Cheng VTM = VectorTypeModifier::FixedSEW8; 5107ff0bf57SKito Cheng break; 5117ff0bf57SKito Cheng case 16: 5127ff0bf57SKito Cheng VTM = VectorTypeModifier::FixedSEW16; 5137ff0bf57SKito Cheng break; 5147ff0bf57SKito Cheng case 32: 5157ff0bf57SKito Cheng VTM = VectorTypeModifier::FixedSEW32; 5167ff0bf57SKito Cheng break; 5177ff0bf57SKito Cheng case 64: 5187ff0bf57SKito Cheng VTM = VectorTypeModifier::FixedSEW64; 5197ff0bf57SKito Cheng break; 5207ff0bf57SKito Cheng default: 5217ff0bf57SKito Cheng llvm_unreachable("Invalid FixedSEW value, should be 8, 16, 32 or 64"); 5225891420eSKazu Hirata return std::nullopt; 5237ff0bf57SKito Cheng } 524f26c41e8SKito Cheng } else if (ComplexTT.first == "LFixedLog2LMUL") { 5257ff0bf57SKito Cheng int32_t Log2LMUL; 5267ff0bf57SKito Cheng if (ComplexTT.second.getAsInteger(10, Log2LMUL)) { 5277ff0bf57SKito Cheng llvm_unreachable("Invalid LFixedLog2LMUL value!"); 5285891420eSKazu Hirata return std::nullopt; 5297ff0bf57SKito Cheng } 5307ff0bf57SKito Cheng switch (Log2LMUL) { 5317ff0bf57SKito Cheng case -3: 5327ff0bf57SKito Cheng VTM = VectorTypeModifier::LFixedLog2LMULN3; 5337ff0bf57SKito Cheng break; 5347ff0bf57SKito Cheng case -2: 5357ff0bf57SKito Cheng VTM = VectorTypeModifier::LFixedLog2LMULN2; 5367ff0bf57SKito Cheng break; 5377ff0bf57SKito Cheng case -1: 5387ff0bf57SKito Cheng VTM = VectorTypeModifier::LFixedLog2LMULN1; 5397ff0bf57SKito Cheng break; 5407ff0bf57SKito Cheng case 0: 5417ff0bf57SKito Cheng VTM = VectorTypeModifier::LFixedLog2LMUL0; 5427ff0bf57SKito Cheng break; 5437ff0bf57SKito Cheng case 1: 5447ff0bf57SKito Cheng VTM = VectorTypeModifier::LFixedLog2LMUL1; 5457ff0bf57SKito Cheng break; 5467ff0bf57SKito Cheng case 2: 5477ff0bf57SKito Cheng VTM = VectorTypeModifier::LFixedLog2LMUL2; 5487ff0bf57SKito Cheng break; 5497ff0bf57SKito Cheng case 3: 5507ff0bf57SKito Cheng VTM = VectorTypeModifier::LFixedLog2LMUL3; 5517ff0bf57SKito Cheng break; 5527ff0bf57SKito Cheng default: 5537ff0bf57SKito Cheng llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]"); 5545891420eSKazu Hirata return std::nullopt; 5557ff0bf57SKito Cheng } 556f26c41e8SKito Cheng } else if (ComplexTT.first == "SFixedLog2LMUL") { 5577ff0bf57SKito Cheng int32_t Log2LMUL; 5587ff0bf57SKito Cheng if (ComplexTT.second.getAsInteger(10, Log2LMUL)) { 5597ff0bf57SKito Cheng llvm_unreachable("Invalid SFixedLog2LMUL value!"); 5605891420eSKazu Hirata return std::nullopt; 5617ff0bf57SKito Cheng } 5627ff0bf57SKito Cheng switch (Log2LMUL) { 5637ff0bf57SKito Cheng case -3: 5647ff0bf57SKito Cheng VTM = VectorTypeModifier::SFixedLog2LMULN3; 5657ff0bf57SKito Cheng break; 5667ff0bf57SKito Cheng case -2: 5677ff0bf57SKito Cheng VTM = VectorTypeModifier::SFixedLog2LMULN2; 5687ff0bf57SKito Cheng break; 5697ff0bf57SKito Cheng case -1: 5707ff0bf57SKito Cheng VTM = VectorTypeModifier::SFixedLog2LMULN1; 5717ff0bf57SKito Cheng break; 5727ff0bf57SKito Cheng case 0: 5737ff0bf57SKito Cheng VTM = VectorTypeModifier::SFixedLog2LMUL0; 5747ff0bf57SKito Cheng break; 5757ff0bf57SKito Cheng case 1: 5767ff0bf57SKito Cheng VTM = VectorTypeModifier::SFixedLog2LMUL1; 5777ff0bf57SKito Cheng break; 5787ff0bf57SKito Cheng case 2: 5797ff0bf57SKito Cheng VTM = VectorTypeModifier::SFixedLog2LMUL2; 5807ff0bf57SKito Cheng break; 5817ff0bf57SKito Cheng case 3: 5827ff0bf57SKito Cheng VTM = VectorTypeModifier::SFixedLog2LMUL3; 5837ff0bf57SKito Cheng break; 5847ff0bf57SKito Cheng default: 5857ff0bf57SKito Cheng llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]"); 5865891420eSKazu Hirata return std::nullopt; 5877ff0bf57SKito Cheng } 5887ff0bf57SKito Cheng 5892a05a521S4vtomat } else if (ComplexTT.first == "SEFixedLog2LMUL") { 5902a05a521S4vtomat int32_t Log2LMUL; 5912a05a521S4vtomat if (ComplexTT.second.getAsInteger(10, Log2LMUL)) { 5922a05a521S4vtomat llvm_unreachable("Invalid SEFixedLog2LMUL value!"); 5932a05a521S4vtomat return std::nullopt; 5942a05a521S4vtomat } 5952a05a521S4vtomat switch (Log2LMUL) { 5962a05a521S4vtomat case -3: 5972a05a521S4vtomat VTM = VectorTypeModifier::SEFixedLog2LMULN3; 5982a05a521S4vtomat break; 5992a05a521S4vtomat case -2: 6002a05a521S4vtomat VTM = VectorTypeModifier::SEFixedLog2LMULN2; 6012a05a521S4vtomat break; 6022a05a521S4vtomat case -1: 6032a05a521S4vtomat VTM = VectorTypeModifier::SEFixedLog2LMULN1; 6042a05a521S4vtomat break; 6052a05a521S4vtomat case 0: 6062a05a521S4vtomat VTM = VectorTypeModifier::SEFixedLog2LMUL0; 6072a05a521S4vtomat break; 6082a05a521S4vtomat case 1: 6092a05a521S4vtomat VTM = VectorTypeModifier::SEFixedLog2LMUL1; 6102a05a521S4vtomat break; 6112a05a521S4vtomat case 2: 6122a05a521S4vtomat VTM = VectorTypeModifier::SEFixedLog2LMUL2; 6132a05a521S4vtomat break; 6142a05a521S4vtomat case 3: 6152a05a521S4vtomat VTM = VectorTypeModifier::SEFixedLog2LMUL3; 6162a05a521S4vtomat break; 6172a05a521S4vtomat default: 6182a05a521S4vtomat llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]"); 6192a05a521S4vtomat return std::nullopt; 6202a05a521S4vtomat } 6210019226cSeopXD } else if (ComplexTT.first == "Tuple") { 6220019226cSeopXD unsigned NF = 0; 6230019226cSeopXD if (ComplexTT.second.getAsInteger(10, NF)) { 6240019226cSeopXD llvm_unreachable("Invalid NF value!"); 6250019226cSeopXD return std::nullopt; 6260019226cSeopXD } 6270e9548bbSeopXD VTM = getTupleVTM(NF); 628f26c41e8SKito Cheng } else { 629f26c41e8SKito Cheng llvm_unreachable("Illegal complex type transformers!"); 630f26c41e8SKito Cheng } 631f26c41e8SKito Cheng } 6327ff0bf57SKito Cheng PD.VTM = static_cast<uint8_t>(VTM); 633f26c41e8SKito Cheng 634f26c41e8SKito Cheng // Compute the remain type transformers 6357ff0bf57SKito Cheng TypeModifier TM = TypeModifier::NoModifier; 6367ff0bf57SKito Cheng for (char I : PrototypeDescriptorStr) { 637f26c41e8SKito Cheng switch (I) { 638f26c41e8SKito Cheng case 'P': 6397ff0bf57SKito Cheng if ((TM & TypeModifier::Const) == TypeModifier::Const) 640f26c41e8SKito Cheng llvm_unreachable("'P' transformer cannot be used after 'C'"); 6417ff0bf57SKito Cheng if ((TM & TypeModifier::Pointer) == TypeModifier::Pointer) 642f26c41e8SKito Cheng llvm_unreachable("'P' transformer cannot be used twice"); 6437ff0bf57SKito Cheng TM |= TypeModifier::Pointer; 644f26c41e8SKito Cheng break; 645f26c41e8SKito Cheng case 'C': 6467ff0bf57SKito Cheng TM |= TypeModifier::Const; 647f26c41e8SKito Cheng break; 648f26c41e8SKito Cheng case 'K': 6497ff0bf57SKito Cheng TM |= TypeModifier::Immediate; 650f26c41e8SKito Cheng break; 651f26c41e8SKito Cheng case 'U': 6527ff0bf57SKito Cheng TM |= TypeModifier::UnsignedInteger; 653f26c41e8SKito Cheng break; 654f26c41e8SKito Cheng case 'I': 6557ff0bf57SKito Cheng TM |= TypeModifier::SignedInteger; 656f26c41e8SKito Cheng break; 657f26c41e8SKito Cheng case 'F': 6587ff0bf57SKito Cheng TM |= TypeModifier::Float; 659f26c41e8SKito Cheng break; 660f26c41e8SKito Cheng case 'S': 6617ff0bf57SKito Cheng TM |= TypeModifier::LMUL1; 662f26c41e8SKito Cheng break; 663f26c41e8SKito Cheng default: 664f26c41e8SKito Cheng llvm_unreachable("Illegal non-primitive type transformer!"); 665f26c41e8SKito Cheng } 666f26c41e8SKito Cheng } 6677ff0bf57SKito Cheng PD.TM = static_cast<uint8_t>(TM); 6687ff0bf57SKito Cheng 6697ff0bf57SKito Cheng return PD; 6707ff0bf57SKito Cheng } 6717ff0bf57SKito Cheng 6727ff0bf57SKito Cheng void RVVType::applyModifier(const PrototypeDescriptor &Transformer) { 6737ff0bf57SKito Cheng // Handle primitive type transformer 6747ff0bf57SKito Cheng switch (static_cast<BaseTypeModifier>(Transformer.PT)) { 6757ff0bf57SKito Cheng case BaseTypeModifier::Scalar: 6767ff0bf57SKito Cheng Scale = 0; 6777ff0bf57SKito Cheng break; 6787ff0bf57SKito Cheng case BaseTypeModifier::Vector: 6797ff0bf57SKito Cheng Scale = LMUL.getScale(ElementBitwidth); 6807ff0bf57SKito Cheng break; 6817ff0bf57SKito Cheng case BaseTypeModifier::Void: 6827ff0bf57SKito Cheng ScalarType = ScalarTypeKind::Void; 6837ff0bf57SKito Cheng break; 6847ff0bf57SKito Cheng case BaseTypeModifier::SizeT: 6857ff0bf57SKito Cheng ScalarType = ScalarTypeKind::Size_t; 6867ff0bf57SKito Cheng break; 6877ff0bf57SKito Cheng case BaseTypeModifier::Ptrdiff: 6887ff0bf57SKito Cheng ScalarType = ScalarTypeKind::Ptrdiff_t; 6897ff0bf57SKito Cheng break; 6907ff0bf57SKito Cheng case BaseTypeModifier::UnsignedLong: 6917ff0bf57SKito Cheng ScalarType = ScalarTypeKind::UnsignedLong; 6927ff0bf57SKito Cheng break; 6937ff0bf57SKito Cheng case BaseTypeModifier::SignedLong: 6947ff0bf57SKito Cheng ScalarType = ScalarTypeKind::SignedLong; 6957ff0bf57SKito Cheng break; 69674f38df1SBrandon Wu case BaseTypeModifier::Float32: 69774f38df1SBrandon Wu ElementBitwidth = 32; 69874f38df1SBrandon Wu ScalarType = ScalarTypeKind::Float; 69974f38df1SBrandon Wu break; 7007ff0bf57SKito Cheng case BaseTypeModifier::Invalid: 7017ff0bf57SKito Cheng ScalarType = ScalarTypeKind::Invalid; 7027ff0bf57SKito Cheng return; 7037ff0bf57SKito Cheng } 7047ff0bf57SKito Cheng 7057ff0bf57SKito Cheng switch (static_cast<VectorTypeModifier>(Transformer.VTM)) { 7067ff0bf57SKito Cheng case VectorTypeModifier::Widening2XVector: 7077ff0bf57SKito Cheng ElementBitwidth *= 2; 708da201aa4SeopXD LMUL.MulLog2LMUL(1); 7097ff0bf57SKito Cheng Scale = LMUL.getScale(ElementBitwidth); 7107ff0bf57SKito Cheng break; 7117ff0bf57SKito Cheng case VectorTypeModifier::Widening4XVector: 7127ff0bf57SKito Cheng ElementBitwidth *= 4; 713da201aa4SeopXD LMUL.MulLog2LMUL(2); 7147ff0bf57SKito Cheng Scale = LMUL.getScale(ElementBitwidth); 7157ff0bf57SKito Cheng break; 7167ff0bf57SKito Cheng case VectorTypeModifier::Widening8XVector: 7177ff0bf57SKito Cheng ElementBitwidth *= 8; 718da201aa4SeopXD LMUL.MulLog2LMUL(3); 7197ff0bf57SKito Cheng Scale = LMUL.getScale(ElementBitwidth); 7207ff0bf57SKito Cheng break; 7217ff0bf57SKito Cheng case VectorTypeModifier::MaskVector: 7227ff0bf57SKito Cheng ScalarType = ScalarTypeKind::Boolean; 7237ff0bf57SKito Cheng Scale = LMUL.getScale(ElementBitwidth); 7247ff0bf57SKito Cheng ElementBitwidth = 1; 7257ff0bf57SKito Cheng break; 7267ff0bf57SKito Cheng case VectorTypeModifier::Log2EEW3: 7277ff0bf57SKito Cheng applyLog2EEW(3); 7287ff0bf57SKito Cheng break; 7297ff0bf57SKito Cheng case VectorTypeModifier::Log2EEW4: 7307ff0bf57SKito Cheng applyLog2EEW(4); 7317ff0bf57SKito Cheng break; 7327ff0bf57SKito Cheng case VectorTypeModifier::Log2EEW5: 7337ff0bf57SKito Cheng applyLog2EEW(5); 7347ff0bf57SKito Cheng break; 7357ff0bf57SKito Cheng case VectorTypeModifier::Log2EEW6: 7367ff0bf57SKito Cheng applyLog2EEW(6); 7377ff0bf57SKito Cheng break; 7387ff0bf57SKito Cheng case VectorTypeModifier::FixedSEW8: 7397ff0bf57SKito Cheng applyFixedSEW(8); 7407ff0bf57SKito Cheng break; 7417ff0bf57SKito Cheng case VectorTypeModifier::FixedSEW16: 7427ff0bf57SKito Cheng applyFixedSEW(16); 7437ff0bf57SKito Cheng break; 7447ff0bf57SKito Cheng case VectorTypeModifier::FixedSEW32: 7457ff0bf57SKito Cheng applyFixedSEW(32); 7467ff0bf57SKito Cheng break; 7477ff0bf57SKito Cheng case VectorTypeModifier::FixedSEW64: 7487ff0bf57SKito Cheng applyFixedSEW(64); 7497ff0bf57SKito Cheng break; 7507ff0bf57SKito Cheng case VectorTypeModifier::LFixedLog2LMULN3: 7517ff0bf57SKito Cheng applyFixedLog2LMUL(-3, FixedLMULType::LargerThan); 7527ff0bf57SKito Cheng break; 7537ff0bf57SKito Cheng case VectorTypeModifier::LFixedLog2LMULN2: 7547ff0bf57SKito Cheng applyFixedLog2LMUL(-2, FixedLMULType::LargerThan); 7557ff0bf57SKito Cheng break; 7567ff0bf57SKito Cheng case VectorTypeModifier::LFixedLog2LMULN1: 7577ff0bf57SKito Cheng applyFixedLog2LMUL(-1, FixedLMULType::LargerThan); 7587ff0bf57SKito Cheng break; 7597ff0bf57SKito Cheng case VectorTypeModifier::LFixedLog2LMUL0: 7607ff0bf57SKito Cheng applyFixedLog2LMUL(0, FixedLMULType::LargerThan); 7617ff0bf57SKito Cheng break; 7627ff0bf57SKito Cheng case VectorTypeModifier::LFixedLog2LMUL1: 7637ff0bf57SKito Cheng applyFixedLog2LMUL(1, FixedLMULType::LargerThan); 7647ff0bf57SKito Cheng break; 7657ff0bf57SKito Cheng case VectorTypeModifier::LFixedLog2LMUL2: 7667ff0bf57SKito Cheng applyFixedLog2LMUL(2, FixedLMULType::LargerThan); 7677ff0bf57SKito Cheng break; 7687ff0bf57SKito Cheng case VectorTypeModifier::LFixedLog2LMUL3: 7697ff0bf57SKito Cheng applyFixedLog2LMUL(3, FixedLMULType::LargerThan); 7707ff0bf57SKito Cheng break; 7717ff0bf57SKito Cheng case VectorTypeModifier::SFixedLog2LMULN3: 7727ff0bf57SKito Cheng applyFixedLog2LMUL(-3, FixedLMULType::SmallerThan); 7737ff0bf57SKito Cheng break; 7747ff0bf57SKito Cheng case VectorTypeModifier::SFixedLog2LMULN2: 7757ff0bf57SKito Cheng applyFixedLog2LMUL(-2, FixedLMULType::SmallerThan); 7767ff0bf57SKito Cheng break; 7777ff0bf57SKito Cheng case VectorTypeModifier::SFixedLog2LMULN1: 7787ff0bf57SKito Cheng applyFixedLog2LMUL(-1, FixedLMULType::SmallerThan); 7797ff0bf57SKito Cheng break; 7807ff0bf57SKito Cheng case VectorTypeModifier::SFixedLog2LMUL0: 7817ff0bf57SKito Cheng applyFixedLog2LMUL(0, FixedLMULType::SmallerThan); 7827ff0bf57SKito Cheng break; 7837ff0bf57SKito Cheng case VectorTypeModifier::SFixedLog2LMUL1: 7847ff0bf57SKito Cheng applyFixedLog2LMUL(1, FixedLMULType::SmallerThan); 7857ff0bf57SKito Cheng break; 7867ff0bf57SKito Cheng case VectorTypeModifier::SFixedLog2LMUL2: 7877ff0bf57SKito Cheng applyFixedLog2LMUL(2, FixedLMULType::SmallerThan); 7887ff0bf57SKito Cheng break; 7897ff0bf57SKito Cheng case VectorTypeModifier::SFixedLog2LMUL3: 7907ff0bf57SKito Cheng applyFixedLog2LMUL(3, FixedLMULType::SmallerThan); 7917ff0bf57SKito Cheng break; 7922a05a521S4vtomat case VectorTypeModifier::SEFixedLog2LMULN3: 7932a05a521S4vtomat applyFixedLog2LMUL(-3, FixedLMULType::SmallerOrEqual); 7942a05a521S4vtomat break; 7952a05a521S4vtomat case VectorTypeModifier::SEFixedLog2LMULN2: 7962a05a521S4vtomat applyFixedLog2LMUL(-2, FixedLMULType::SmallerOrEqual); 7972a05a521S4vtomat break; 7982a05a521S4vtomat case VectorTypeModifier::SEFixedLog2LMULN1: 7992a05a521S4vtomat applyFixedLog2LMUL(-1, FixedLMULType::SmallerOrEqual); 8002a05a521S4vtomat break; 8012a05a521S4vtomat case VectorTypeModifier::SEFixedLog2LMUL0: 8022a05a521S4vtomat applyFixedLog2LMUL(0, FixedLMULType::SmallerOrEqual); 8032a05a521S4vtomat break; 8042a05a521S4vtomat case VectorTypeModifier::SEFixedLog2LMUL1: 8052a05a521S4vtomat applyFixedLog2LMUL(1, FixedLMULType::SmallerOrEqual); 8062a05a521S4vtomat break; 8072a05a521S4vtomat case VectorTypeModifier::SEFixedLog2LMUL2: 8082a05a521S4vtomat applyFixedLog2LMUL(2, FixedLMULType::SmallerOrEqual); 8092a05a521S4vtomat break; 8102a05a521S4vtomat case VectorTypeModifier::SEFixedLog2LMUL3: 8112a05a521S4vtomat applyFixedLog2LMUL(3, FixedLMULType::SmallerOrEqual); 8122a05a521S4vtomat break; 8135847ec4dSeopXD case VectorTypeModifier::Tuple2: 8145847ec4dSeopXD case VectorTypeModifier::Tuple3: 8155847ec4dSeopXD case VectorTypeModifier::Tuple4: 8165847ec4dSeopXD case VectorTypeModifier::Tuple5: 8175847ec4dSeopXD case VectorTypeModifier::Tuple6: 8185847ec4dSeopXD case VectorTypeModifier::Tuple7: 8195847ec4dSeopXD case VectorTypeModifier::Tuple8: { 8200019226cSeopXD IsTuple = true; 8215847ec4dSeopXD NF = 2 + static_cast<uint8_t>(Transformer.VTM) - 8225847ec4dSeopXD static_cast<uint8_t>(VectorTypeModifier::Tuple2); 8230019226cSeopXD break; 8240019226cSeopXD } 8257ff0bf57SKito Cheng case VectorTypeModifier::NoModifier: 8267ff0bf57SKito Cheng break; 8277ff0bf57SKito Cheng } 8287ff0bf57SKito Cheng 829f3ce9250S4vtomat // Early return if the current type modifier is already invalid. 830f3ce9250S4vtomat if (ScalarType == Invalid) 831f3ce9250S4vtomat return; 832f3ce9250S4vtomat 8337ff0bf57SKito Cheng for (unsigned TypeModifierMaskShift = 0; 8347ff0bf57SKito Cheng TypeModifierMaskShift <= static_cast<unsigned>(TypeModifier::MaxOffset); 8357ff0bf57SKito Cheng ++TypeModifierMaskShift) { 8367ff0bf57SKito Cheng unsigned TypeModifierMask = 1 << TypeModifierMaskShift; 8377ff0bf57SKito Cheng if ((static_cast<unsigned>(Transformer.TM) & TypeModifierMask) != 8387ff0bf57SKito Cheng TypeModifierMask) 8397ff0bf57SKito Cheng continue; 8407ff0bf57SKito Cheng switch (static_cast<TypeModifier>(TypeModifierMask)) { 8417ff0bf57SKito Cheng case TypeModifier::Pointer: 8427ff0bf57SKito Cheng IsPointer = true; 8437ff0bf57SKito Cheng break; 8447ff0bf57SKito Cheng case TypeModifier::Const: 8457ff0bf57SKito Cheng IsConstant = true; 8467ff0bf57SKito Cheng break; 8477ff0bf57SKito Cheng case TypeModifier::Immediate: 8487ff0bf57SKito Cheng IsImmediate = true; 8497ff0bf57SKito Cheng IsConstant = true; 8507ff0bf57SKito Cheng break; 8517ff0bf57SKito Cheng case TypeModifier::UnsignedInteger: 8527ff0bf57SKito Cheng ScalarType = ScalarTypeKind::UnsignedInteger; 8537ff0bf57SKito Cheng break; 8547ff0bf57SKito Cheng case TypeModifier::SignedInteger: 8557ff0bf57SKito Cheng ScalarType = ScalarTypeKind::SignedInteger; 8567ff0bf57SKito Cheng break; 8577ff0bf57SKito Cheng case TypeModifier::Float: 8587ff0bf57SKito Cheng ScalarType = ScalarTypeKind::Float; 8597ff0bf57SKito Cheng break; 8601c937819SYueh-Ting (eop) Chen case TypeModifier::BFloat: 8611c937819SYueh-Ting (eop) Chen ScalarType = ScalarTypeKind::BFloat; 8621c937819SYueh-Ting (eop) Chen break; 8637ff0bf57SKito Cheng case TypeModifier::LMUL1: 8647ff0bf57SKito Cheng LMUL = LMULType(0); 8657ff0bf57SKito Cheng // Update ElementBitwidth need to update Scale too. 8667ff0bf57SKito Cheng Scale = LMUL.getScale(ElementBitwidth); 8677ff0bf57SKito Cheng break; 8687ff0bf57SKito Cheng default: 8697ff0bf57SKito Cheng llvm_unreachable("Unknown type modifier mask!"); 8707ff0bf57SKito Cheng } 8717ff0bf57SKito Cheng } 8727ff0bf57SKito Cheng } 8737ff0bf57SKito Cheng 8747ff0bf57SKito Cheng void RVVType::applyLog2EEW(unsigned Log2EEW) { 8757ff0bf57SKito Cheng // update new elmul = (eew/sew) * lmul 8767ff0bf57SKito Cheng LMUL.MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth)); 8777ff0bf57SKito Cheng // update new eew 8787ff0bf57SKito Cheng ElementBitwidth = 1 << Log2EEW; 8797ff0bf57SKito Cheng ScalarType = ScalarTypeKind::SignedInteger; 8807ff0bf57SKito Cheng Scale = LMUL.getScale(ElementBitwidth); 8817ff0bf57SKito Cheng } 8827ff0bf57SKito Cheng 8837ff0bf57SKito Cheng void RVVType::applyFixedSEW(unsigned NewSEW) { 8847ff0bf57SKito Cheng // Set invalid type if src and dst SEW are same. 8857ff0bf57SKito Cheng if (ElementBitwidth == NewSEW) { 8867ff0bf57SKito Cheng ScalarType = ScalarTypeKind::Invalid; 8877ff0bf57SKito Cheng return; 8887ff0bf57SKito Cheng } 8897ff0bf57SKito Cheng // Update new SEW 8907ff0bf57SKito Cheng ElementBitwidth = NewSEW; 8917ff0bf57SKito Cheng Scale = LMUL.getScale(ElementBitwidth); 8927ff0bf57SKito Cheng } 8937ff0bf57SKito Cheng 8947ff0bf57SKito Cheng void RVVType::applyFixedLog2LMUL(int Log2LMUL, enum FixedLMULType Type) { 8957ff0bf57SKito Cheng switch (Type) { 8967ff0bf57SKito Cheng case FixedLMULType::LargerThan: 897f3ce9250S4vtomat if (Log2LMUL <= LMUL.Log2LMUL) { 8987ff0bf57SKito Cheng ScalarType = ScalarTypeKind::Invalid; 8997ff0bf57SKito Cheng return; 9007ff0bf57SKito Cheng } 9017ff0bf57SKito Cheng break; 9027ff0bf57SKito Cheng case FixedLMULType::SmallerThan: 903f3ce9250S4vtomat if (Log2LMUL >= LMUL.Log2LMUL) { 9047ff0bf57SKito Cheng ScalarType = ScalarTypeKind::Invalid; 9057ff0bf57SKito Cheng return; 9067ff0bf57SKito Cheng } 9077ff0bf57SKito Cheng break; 9082a05a521S4vtomat case FixedLMULType::SmallerOrEqual: 9092a05a521S4vtomat if (Log2LMUL > LMUL.Log2LMUL) { 9102a05a521S4vtomat ScalarType = ScalarTypeKind::Invalid; 9112a05a521S4vtomat return; 9122a05a521S4vtomat } 9132a05a521S4vtomat break; 9147ff0bf57SKito Cheng } 9157ff0bf57SKito Cheng 9167ff0bf57SKito Cheng // Update new LMUL 9177ff0bf57SKito Cheng LMUL = LMULType(Log2LMUL); 9187ff0bf57SKito Cheng Scale = LMUL.getScale(ElementBitwidth); 9197ff0bf57SKito Cheng } 9207ff0bf57SKito Cheng 9219cf4419eSKazu Hirata std::optional<RVVTypes> 9223fe89be8SKito Cheng RVVTypeCache::computeTypes(BasicType BT, int Log2LMUL, unsigned NF, 92379e3d57fSZakk Chen ArrayRef<PrototypeDescriptor> Prototype) { 9247ff0bf57SKito Cheng RVVTypes Types; 92579e3d57fSZakk Chen for (const PrototypeDescriptor &Proto : Prototype) { 9267ff0bf57SKito Cheng auto T = computeType(BT, Log2LMUL, Proto); 92797afce08SKazu Hirata if (!T) 9285891420eSKazu Hirata return std::nullopt; 9297ff0bf57SKito Cheng // Record legal type index 930fc6ca0d0SFangrui Song Types.push_back(*T); 9317ff0bf57SKito Cheng } 9327ff0bf57SKito Cheng return Types; 9337ff0bf57SKito Cheng } 9347ff0bf57SKito Cheng 9357ff0bf57SKito Cheng // Compute the hash value of RVVType, used for cache the result of computeType. 9367ff0bf57SKito Cheng static uint64_t computeRVVTypeHashValue(BasicType BT, int Log2LMUL, 9377ff0bf57SKito Cheng PrototypeDescriptor Proto) { 9387ff0bf57SKito Cheng // Layout of hash value: 9397ff0bf57SKito Cheng // 0 8 16 24 32 40 9407ff0bf57SKito Cheng // | Log2LMUL + 3 | BT | Proto.PT | Proto.TM | Proto.VTM | 9417ff0bf57SKito Cheng assert(Log2LMUL >= -3 && Log2LMUL <= 3); 9427ff0bf57SKito Cheng return (Log2LMUL + 3) | (static_cast<uint64_t>(BT) & 0xff) << 8 | 9437ff0bf57SKito Cheng ((uint64_t)(Proto.PT & 0xff) << 16) | 9447ff0bf57SKito Cheng ((uint64_t)(Proto.TM & 0xff) << 24) | 9457ff0bf57SKito Cheng ((uint64_t)(Proto.VTM & 0xff) << 32); 9467ff0bf57SKito Cheng } 9477ff0bf57SKito Cheng 9489cf4419eSKazu Hirata std::optional<RVVTypePtr> RVVTypeCache::computeType(BasicType BT, int Log2LMUL, 9497ff0bf57SKito Cheng PrototypeDescriptor Proto) { 9507ff0bf57SKito Cheng uint64_t Idx = computeRVVTypeHashValue(BT, Log2LMUL, Proto); 9517ff0bf57SKito Cheng // Search first 9527ff0bf57SKito Cheng auto It = LegalTypes.find(Idx); 9537ff0bf57SKito Cheng if (It != LegalTypes.end()) 9547ff0bf57SKito Cheng return &(It->second); 9557ff0bf57SKito Cheng 9567ff0bf57SKito Cheng if (IllegalTypes.count(Idx)) 9575891420eSKazu Hirata return std::nullopt; 9587ff0bf57SKito Cheng 9597ff0bf57SKito Cheng // Compute type and record the result. 9607ff0bf57SKito Cheng RVVType T(BT, Log2LMUL, Proto); 9617ff0bf57SKito Cheng if (T.isValid()) { 9627ff0bf57SKito Cheng // Record legal type index and value. 9633fe89be8SKito Cheng std::pair<std::unordered_map<uint64_t, RVVType>::iterator, bool> 9643fe89be8SKito Cheng InsertResult = LegalTypes.insert({Idx, T}); 9653fe89be8SKito Cheng return &(InsertResult.first->second); 9667ff0bf57SKito Cheng } 9677ff0bf57SKito Cheng // Record illegal type index. 9687ff0bf57SKito Cheng IllegalTypes.insert(Idx); 9695891420eSKazu Hirata return std::nullopt; 970f26c41e8SKito Cheng } 971f26c41e8SKito Cheng 972f26c41e8SKito Cheng //===----------------------------------------------------------------------===// 973f26c41e8SKito Cheng // RVVIntrinsic implementation 974f26c41e8SKito Cheng //===----------------------------------------------------------------------===// 97576482078SeopXD RVVIntrinsic::RVVIntrinsic( 97676482078SeopXD StringRef NewName, StringRef Suffix, StringRef NewOverloadedName, 97776482078SeopXD StringRef OverloadedSuffix, StringRef IRName, bool IsMasked, 97876482078SeopXD bool HasMaskedOffOperand, bool HasVL, PolicyScheme Scheme, 97976482078SeopXD bool SupportOverloading, bool HasBuiltinAlias, StringRef ManualCodegen, 98076482078SeopXD const RVVTypes &OutInTypes, const std::vector<int64_t> &NewIntrinsicTypes, 98184741940SCraig Topper unsigned NF, Policy NewPolicyAttrs, bool HasFRMRoundModeOp) 98271fd6616SZakk Chen : IRName(IRName), IsMasked(IsMasked), 98371fd6616SZakk Chen HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme), 98471fd6616SZakk Chen SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias), 985405889ebSJie Fu ManualCodegen(ManualCodegen.str()), NF(NF), PolicyAttrs(NewPolicyAttrs) { 986f26c41e8SKito Cheng 98779e3d57fSZakk Chen // Init BuiltinName, Name and OverloadedName 988f26c41e8SKito Cheng BuiltinName = NewName.str(); 989f26c41e8SKito Cheng Name = BuiltinName; 99079e3d57fSZakk Chen if (NewOverloadedName.empty()) 99179e3d57fSZakk Chen OverloadedName = NewName.split("_").first.str(); 992f26c41e8SKito Cheng else 99379e3d57fSZakk Chen OverloadedName = NewOverloadedName.str(); 994f26c41e8SKito Cheng if (!Suffix.empty()) 995f26c41e8SKito Cheng Name += "_" + Suffix.str(); 99679e3d57fSZakk Chen if (!OverloadedSuffix.empty()) 99779e3d57fSZakk Chen OverloadedName += "_" + OverloadedSuffix.str(); 99871fd6616SZakk Chen 9996b282294SeopXD updateNamesAndPolicy(IsMasked, hasPolicy(), Name, BuiltinName, OverloadedName, 100076482078SeopXD PolicyAttrs, HasFRMRoundModeOp); 1001f26c41e8SKito Cheng 1002f26c41e8SKito Cheng // Init OutputType and InputTypes 1003f26c41e8SKito Cheng OutputType = OutInTypes[0]; 1004f26c41e8SKito Cheng InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end()); 1005f26c41e8SKito Cheng 1006f26c41e8SKito Cheng // IntrinsicTypes is unmasked TA version index. Need to update it 1007f26c41e8SKito Cheng // if there is merge operand (It is always in first operand). 1008f26c41e8SKito Cheng IntrinsicTypes = NewIntrinsicTypes; 100971fd6616SZakk Chen if ((IsMasked && hasMaskedOffOperand()) || 10106b282294SeopXD (!IsMasked && hasPassthruOperand())) { 1011f26c41e8SKito Cheng for (auto &I : IntrinsicTypes) { 1012f26c41e8SKito Cheng if (I >= 0) 1013*239127d7SBrandon Wu I += 1; 1014f26c41e8SKito Cheng } 1015f26c41e8SKito Cheng } 1016f26c41e8SKito Cheng } 1017f26c41e8SKito Cheng 1018f26c41e8SKito Cheng std::string RVVIntrinsic::getBuiltinTypeStr() const { 1019f26c41e8SKito Cheng std::string S; 1020f26c41e8SKito Cheng S += OutputType->getBuiltinStr(); 1021f26c41e8SKito Cheng for (const auto &T : InputTypes) { 1022f26c41e8SKito Cheng S += T->getBuiltinStr(); 1023f26c41e8SKito Cheng } 1024f26c41e8SKito Cheng return S; 1025f26c41e8SKito Cheng } 1026f26c41e8SKito Cheng 10277ff0bf57SKito Cheng std::string RVVIntrinsic::getSuffixStr( 10283fe89be8SKito Cheng RVVTypeCache &TypeCache, BasicType Type, int Log2LMUL, 1029b166aa83SKito Cheng llvm::ArrayRef<PrototypeDescriptor> PrototypeDescriptors) { 10307ff0bf57SKito Cheng SmallVector<std::string> SuffixStrs; 10317ff0bf57SKito Cheng for (auto PD : PrototypeDescriptors) { 10323fe89be8SKito Cheng auto T = TypeCache.computeType(Type, Log2LMUL, PD); 1033ca4af13eSKazu Hirata SuffixStrs.push_back((*T)->getShortStr()); 10347ff0bf57SKito Cheng } 10357ff0bf57SKito Cheng return join(SuffixStrs, "_"); 10367ff0bf57SKito Cheng } 10377ff0bf57SKito Cheng 103871fd6616SZakk Chen llvm::SmallVector<PrototypeDescriptor> RVVIntrinsic::computeBuiltinTypes( 103971fd6616SZakk Chen llvm::ArrayRef<PrototypeDescriptor> Prototype, bool IsMasked, 104071fd6616SZakk Chen bool HasMaskedOffOperand, bool HasVL, unsigned NF, 10410019226cSeopXD PolicyScheme DefaultScheme, Policy PolicyAttrs, bool IsTuple) { 10421fa7f05bSKazu Hirata SmallVector<PrototypeDescriptor> NewPrototype(Prototype); 1043dffdca85SZakk Chen bool HasPassthruOp = DefaultScheme == PolicyScheme::HasPassthruOperand; 1044bc4eef50SZakk Chen if (IsMasked) { 104571fd6616SZakk Chen // If HasMaskedOffOperand, insert result type as first input operand if 104671fd6616SZakk Chen // need. 10471deb6bceSeopXD if (HasMaskedOffOperand && !PolicyAttrs.isTAMAPolicy()) { 1048010f3298SZakk Chen if (NF == 1) { 1049bc4eef50SZakk Chen NewPrototype.insert(NewPrototype.begin() + 1, NewPrototype[0]); 105071fd6616SZakk Chen } else if (NF > 1) { 10510e9548bbSeopXD if (IsTuple) { 10520e9548bbSeopXD PrototypeDescriptor BasePtrOperand = Prototype[1]; 10530e9548bbSeopXD PrototypeDescriptor MaskoffType = PrototypeDescriptor( 10540e9548bbSeopXD static_cast<uint8_t>(BaseTypeModifier::Vector), 10550e9548bbSeopXD static_cast<uint8_t>(getTupleVTM(NF)), 10560e9548bbSeopXD BasePtrOperand.TM & ~static_cast<uint8_t>(TypeModifier::Pointer)); 10570e9548bbSeopXD NewPrototype.insert(NewPrototype.begin() + 1, MaskoffType); 10580e9548bbSeopXD } else { 1059bc4eef50SZakk Chen // Convert 1060bc4eef50SZakk Chen // (void, op0 address, op1 address, ...) 1061bc4eef50SZakk Chen // to 1062bc4eef50SZakk Chen // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...) 1063bc4eef50SZakk Chen PrototypeDescriptor MaskoffType = NewPrototype[1]; 1064bc4eef50SZakk Chen MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer); 1065904a79f9SeopXD NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType); 1066bc4eef50SZakk Chen } 1067bc4eef50SZakk Chen } 10680e9548bbSeopXD } 1069bc4eef50SZakk Chen if (HasMaskedOffOperand && NF > 1) { 1070bc4eef50SZakk Chen // Convert 1071bc4eef50SZakk Chen // (void, op0 address, op1 address, ..., maskedoff0, maskedoff1, ...) 1072bc4eef50SZakk Chen // to 1073bc4eef50SZakk Chen // (void, op0 address, op1 address, ..., mask, maskedoff0, maskedoff1, 1074bc4eef50SZakk Chen // ...) 10750019226cSeopXD if (IsTuple) 10760019226cSeopXD NewPrototype.insert(NewPrototype.begin() + 1, 10770019226cSeopXD PrototypeDescriptor::Mask); 10780019226cSeopXD else 1079bc4eef50SZakk Chen NewPrototype.insert(NewPrototype.begin() + NF + 1, 1080bc4eef50SZakk Chen PrototypeDescriptor::Mask); 1081bc4eef50SZakk Chen } else { 1082bc4eef50SZakk Chen // If IsMasked, insert PrototypeDescriptor:Mask as first input operand. 1083bc4eef50SZakk Chen NewPrototype.insert(NewPrototype.begin() + 1, PrototypeDescriptor::Mask); 1084bc4eef50SZakk Chen } 1085010f3298SZakk Chen } else { 1086010f3298SZakk Chen if (NF == 1) { 10876b282294SeopXD if (PolicyAttrs.isTUPolicy() && HasPassthruOp) 108871fd6616SZakk Chen NewPrototype.insert(NewPrototype.begin(), NewPrototype[0]); 10891deb6bceSeopXD } else if (PolicyAttrs.isTUPolicy() && HasPassthruOp) { 10900e9548bbSeopXD if (IsTuple) { 10910e9548bbSeopXD PrototypeDescriptor BasePtrOperand = Prototype[0]; 10920e9548bbSeopXD PrototypeDescriptor MaskoffType = PrototypeDescriptor( 10930e9548bbSeopXD static_cast<uint8_t>(BaseTypeModifier::Vector), 10940e9548bbSeopXD static_cast<uint8_t>(getTupleVTM(NF)), 10950e9548bbSeopXD BasePtrOperand.TM & ~static_cast<uint8_t>(TypeModifier::Pointer)); 10960e9548bbSeopXD NewPrototype.insert(NewPrototype.begin(), MaskoffType); 10970e9548bbSeopXD } else { 1098010f3298SZakk Chen // NF > 1 cases for segment load operations. 1099010f3298SZakk Chen // Convert 1100010f3298SZakk Chen // (void, op0 address, op1 address, ...) 1101010f3298SZakk Chen // to 1102010f3298SZakk Chen // (void, op0 address, op1 address, maskedoff0, maskedoff1, ...) 1103010f3298SZakk Chen PrototypeDescriptor MaskoffType = Prototype[1]; 1104010f3298SZakk Chen MaskoffType.TM &= ~static_cast<uint8_t>(TypeModifier::Pointer); 1105904a79f9SeopXD NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType); 1106010f3298SZakk Chen } 1107bc4eef50SZakk Chen } 11080e9548bbSeopXD } 1109bc4eef50SZakk Chen 1110bc4eef50SZakk Chen // If HasVL, append PrototypeDescriptor:VL to last operand 1111bc4eef50SZakk Chen if (HasVL) 1112bc4eef50SZakk Chen NewPrototype.push_back(PrototypeDescriptor::VL); 11135847ec4dSeopXD 1114bc4eef50SZakk Chen return NewPrototype; 1115bc4eef50SZakk Chen } 1116bc4eef50SZakk Chen 1117d94a315eSeopXD llvm::SmallVector<Policy> RVVIntrinsic::getSupportedUnMaskedPolicies() { 1118d94a315eSeopXD return {Policy(Policy::PolicyType::Undisturbed)}; // TU 111962449823SeopXD } 112062449823SeopXD 112171fd6616SZakk Chen llvm::SmallVector<Policy> 112271fd6616SZakk Chen RVVIntrinsic::getSupportedMaskedPolicies(bool HasTailPolicy, 112371fd6616SZakk Chen bool HasMaskPolicy) { 112471fd6616SZakk Chen if (HasTailPolicy && HasMaskPolicy) 1125d94a315eSeopXD return {Policy(Policy::PolicyType::Undisturbed, 1126d94a315eSeopXD Policy::PolicyType::Agnostic), // TUM 1127d94a315eSeopXD Policy(Policy::PolicyType::Undisturbed, 1128d94a315eSeopXD Policy::PolicyType::Undisturbed), // TUMU 1129d94a315eSeopXD Policy(Policy::PolicyType::Agnostic, 1130d94a315eSeopXD Policy::PolicyType::Undisturbed)}; // MU 113106380284SeopXD if (HasTailPolicy && !HasMaskPolicy) 11320d4c6506SPiyou Chen return {Policy(Policy::PolicyType::Undisturbed, 1133d94a315eSeopXD Policy::PolicyType::Agnostic)}; // TU 113406380284SeopXD if (!HasTailPolicy && HasMaskPolicy) 1135d94a315eSeopXD return {Policy(Policy::PolicyType::Agnostic, 1136d94a315eSeopXD Policy::PolicyType::Undisturbed)}; // MU 113706380284SeopXD llvm_unreachable("An RVV instruction should not be without both tail policy " 113806380284SeopXD "and mask policy"); 113971fd6616SZakk Chen } 114071fd6616SZakk Chen 114176482078SeopXD void RVVIntrinsic::updateNamesAndPolicy( 114276482078SeopXD bool IsMasked, bool HasPolicy, std::string &Name, std::string &BuiltinName, 114376482078SeopXD std::string &OverloadedName, Policy &PolicyAttrs, bool HasFRMRoundModeOp) { 114471fd6616SZakk Chen 114571fd6616SZakk Chen auto appendPolicySuffix = [&](const std::string &suffix) { 114671fd6616SZakk Chen Name += suffix; 114771fd6616SZakk Chen BuiltinName += suffix; 114871fd6616SZakk Chen OverloadedName += suffix; 114971fd6616SZakk Chen }; 115071fd6616SZakk Chen 115176482078SeopXD if (HasFRMRoundModeOp) { 115276482078SeopXD Name += "_rm"; 115376482078SeopXD BuiltinName += "_rm"; 115476482078SeopXD } 115576482078SeopXD 115671fd6616SZakk Chen if (IsMasked) { 1157d94a315eSeopXD if (PolicyAttrs.isTUMUPolicy()) 1158d94a315eSeopXD appendPolicySuffix("_tumu"); 1159d94a315eSeopXD else if (PolicyAttrs.isTUMAPolicy()) 1160d94a315eSeopXD appendPolicySuffix("_tum"); 1161d94a315eSeopXD else if (PolicyAttrs.isTAMUPolicy()) 1162d94a315eSeopXD appendPolicySuffix("_mu"); 1163d94a315eSeopXD else if (PolicyAttrs.isTAMAPolicy()) { 116471fd6616SZakk Chen Name += "_m"; 116571fd6616SZakk Chen BuiltinName += "_m"; 1166d94a315eSeopXD } else 1167377d2604SeopXD llvm_unreachable("Unhandled policy condition"); 1168377d2604SeopXD } else { 1169377d2604SeopXD if (PolicyAttrs.isTUPolicy()) 11700d4c6506SPiyou Chen appendPolicySuffix("_tu"); 11715704630eSeopXD else if (PolicyAttrs.isTAPolicy()) // no suffix needed 11725704630eSeopXD return; 11735704630eSeopXD else 11746f0d0be5SeopXD llvm_unreachable("Unhandled policy condition"); 117571fd6616SZakk Chen } 117671fd6616SZakk Chen } 117771fd6616SZakk Chen 11787ff0bf57SKito Cheng SmallVector<PrototypeDescriptor> parsePrototypes(StringRef Prototypes) { 11797ff0bf57SKito Cheng SmallVector<PrototypeDescriptor> PrototypeDescriptors; 118074f38df1SBrandon Wu const StringRef Primaries("evwqom0ztulf"); 11817ff0bf57SKito Cheng while (!Prototypes.empty()) { 11827ff0bf57SKito Cheng size_t Idx = 0; 11837ff0bf57SKito Cheng // Skip over complex prototype because it could contain primitive type 11847ff0bf57SKito Cheng // character. 11857ff0bf57SKito Cheng if (Prototypes[0] == '(') 11867ff0bf57SKito Cheng Idx = Prototypes.find_first_of(')'); 11877ff0bf57SKito Cheng Idx = Prototypes.find_first_of(Primaries, Idx); 11887ff0bf57SKito Cheng assert(Idx != StringRef::npos); 11897ff0bf57SKito Cheng auto PD = PrototypeDescriptor::parsePrototypeDescriptor( 11907ff0bf57SKito Cheng Prototypes.slice(0, Idx + 1)); 11917ff0bf57SKito Cheng if (!PD) 11927ff0bf57SKito Cheng llvm_unreachable("Error during parsing prototype."); 11937ff0bf57SKito Cheng PrototypeDescriptors.push_back(*PD); 11947ff0bf57SKito Cheng Prototypes = Prototypes.drop_front(Idx + 1); 11957ff0bf57SKito Cheng } 11967ff0bf57SKito Cheng return PrototypeDescriptors; 11977ff0bf57SKito Cheng } 11987ff0bf57SKito Cheng 11997a5cb15eSKito Cheng raw_ostream &operator<<(raw_ostream &OS, const RVVIntrinsicRecord &Record) { 12007a5cb15eSKito Cheng OS << "{"; 12017a5cb15eSKito Cheng OS << "\"" << Record.Name << "\","; 12027a5cb15eSKito Cheng if (Record.OverloadedName == nullptr || 12037a5cb15eSKito Cheng StringRef(Record.OverloadedName).empty()) 12047a5cb15eSKito Cheng OS << "nullptr,"; 12057a5cb15eSKito Cheng else 12067a5cb15eSKito Cheng OS << "\"" << Record.OverloadedName << "\","; 12077a5cb15eSKito Cheng OS << Record.PrototypeIndex << ","; 12087a5cb15eSKito Cheng OS << Record.SuffixIndex << ","; 12097a5cb15eSKito Cheng OS << Record.OverloadedSuffixIndex << ","; 12107a5cb15eSKito Cheng OS << (int)Record.PrototypeLength << ","; 12117a5cb15eSKito Cheng OS << (int)Record.SuffixLength << ","; 12127a5cb15eSKito Cheng OS << (int)Record.OverloadedSuffixSize << ","; 121309058654SEric Biggers OS << Record.RequiredExtensions << ","; 12147a5cb15eSKito Cheng OS << (int)Record.TypeRangeMask << ","; 12157a5cb15eSKito Cheng OS << (int)Record.Log2LMULMask << ","; 12167a5cb15eSKito Cheng OS << (int)Record.NF << ","; 121793f8657cSZakk Chen OS << (int)Record.HasMasked << ","; 121893f8657cSZakk Chen OS << (int)Record.HasVL << ","; 121993f8657cSZakk Chen OS << (int)Record.HasMaskedOffOperand << ","; 122071fd6616SZakk Chen OS << (int)Record.HasTailPolicy << ","; 122171fd6616SZakk Chen OS << (int)Record.HasMaskPolicy << ","; 122276482078SeopXD OS << (int)Record.HasFRMRoundModeOp << ","; 12230019226cSeopXD OS << (int)Record.IsTuple << ","; 122471fd6616SZakk Chen OS << (int)Record.UnMaskedPolicyScheme << ","; 122571fd6616SZakk Chen OS << (int)Record.MaskedPolicyScheme << ","; 12267a5cb15eSKito Cheng OS << "},\n"; 12277a5cb15eSKito Cheng return OS; 12287a5cb15eSKito Cheng } 12297a5cb15eSKito Cheng 1230f26c41e8SKito Cheng } // end namespace RISCV 1231f26c41e8SKito Cheng } // end namespace clang 1232