1*81ad6265SDimitry Andric //===- RISCVVIntrinsicUtils.cpp - RISC-V Vector Intrinsic Utils -*- C++ -*-===// 2*81ad6265SDimitry Andric // 3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*81ad6265SDimitry Andric // 7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 8*81ad6265SDimitry Andric 9*81ad6265SDimitry Andric #include "clang/Support/RISCVVIntrinsicUtils.h" 10*81ad6265SDimitry Andric #include "llvm/ADT/ArrayRef.h" 11*81ad6265SDimitry Andric #include "llvm/ADT/Optional.h" 12*81ad6265SDimitry Andric #include "llvm/ADT/SmallSet.h" 13*81ad6265SDimitry Andric #include "llvm/ADT/StringExtras.h" 14*81ad6265SDimitry Andric #include "llvm/ADT/StringMap.h" 15*81ad6265SDimitry Andric #include "llvm/ADT/StringSet.h" 16*81ad6265SDimitry Andric #include "llvm/ADT/Twine.h" 17*81ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h" 18*81ad6265SDimitry Andric #include <numeric> 19*81ad6265SDimitry Andric #include <set> 20*81ad6265SDimitry Andric #include <unordered_map> 21*81ad6265SDimitry Andric 22*81ad6265SDimitry Andric using namespace llvm; 23*81ad6265SDimitry Andric 24*81ad6265SDimitry Andric namespace clang { 25*81ad6265SDimitry Andric namespace RISCV { 26*81ad6265SDimitry Andric 27*81ad6265SDimitry Andric const PrototypeDescriptor PrototypeDescriptor::Mask = PrototypeDescriptor( 28*81ad6265SDimitry Andric BaseTypeModifier::Vector, VectorTypeModifier::MaskVector); 29*81ad6265SDimitry Andric const PrototypeDescriptor PrototypeDescriptor::VL = 30*81ad6265SDimitry Andric PrototypeDescriptor(BaseTypeModifier::SizeT); 31*81ad6265SDimitry Andric const PrototypeDescriptor PrototypeDescriptor::Vector = 32*81ad6265SDimitry Andric PrototypeDescriptor(BaseTypeModifier::Vector); 33*81ad6265SDimitry Andric 34*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 35*81ad6265SDimitry Andric // Type implementation 36*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 37*81ad6265SDimitry Andric 38*81ad6265SDimitry Andric LMULType::LMULType(int NewLog2LMUL) { 39*81ad6265SDimitry Andric // Check Log2LMUL is -3, -2, -1, 0, 1, 2, 3 40*81ad6265SDimitry Andric assert(NewLog2LMUL <= 3 && NewLog2LMUL >= -3 && "Bad LMUL number!"); 41*81ad6265SDimitry Andric Log2LMUL = NewLog2LMUL; 42*81ad6265SDimitry Andric } 43*81ad6265SDimitry Andric 44*81ad6265SDimitry Andric std::string LMULType::str() const { 45*81ad6265SDimitry Andric if (Log2LMUL < 0) 46*81ad6265SDimitry Andric return "mf" + utostr(1ULL << (-Log2LMUL)); 47*81ad6265SDimitry Andric return "m" + utostr(1ULL << Log2LMUL); 48*81ad6265SDimitry Andric } 49*81ad6265SDimitry Andric 50*81ad6265SDimitry Andric VScaleVal LMULType::getScale(unsigned ElementBitwidth) const { 51*81ad6265SDimitry Andric int Log2ScaleResult = 0; 52*81ad6265SDimitry Andric switch (ElementBitwidth) { 53*81ad6265SDimitry Andric default: 54*81ad6265SDimitry Andric break; 55*81ad6265SDimitry Andric case 8: 56*81ad6265SDimitry Andric Log2ScaleResult = Log2LMUL + 3; 57*81ad6265SDimitry Andric break; 58*81ad6265SDimitry Andric case 16: 59*81ad6265SDimitry Andric Log2ScaleResult = Log2LMUL + 2; 60*81ad6265SDimitry Andric break; 61*81ad6265SDimitry Andric case 32: 62*81ad6265SDimitry Andric Log2ScaleResult = Log2LMUL + 1; 63*81ad6265SDimitry Andric break; 64*81ad6265SDimitry Andric case 64: 65*81ad6265SDimitry Andric Log2ScaleResult = Log2LMUL; 66*81ad6265SDimitry Andric break; 67*81ad6265SDimitry Andric } 68*81ad6265SDimitry Andric // Illegal vscale result would be less than 1 69*81ad6265SDimitry Andric if (Log2ScaleResult < 0) 70*81ad6265SDimitry Andric return llvm::None; 71*81ad6265SDimitry Andric return 1 << Log2ScaleResult; 72*81ad6265SDimitry Andric } 73*81ad6265SDimitry Andric 74*81ad6265SDimitry Andric void LMULType::MulLog2LMUL(int log2LMUL) { Log2LMUL += log2LMUL; } 75*81ad6265SDimitry Andric 76*81ad6265SDimitry Andric RVVType::RVVType(BasicType BT, int Log2LMUL, 77*81ad6265SDimitry Andric const PrototypeDescriptor &prototype) 78*81ad6265SDimitry Andric : BT(BT), LMUL(LMULType(Log2LMUL)) { 79*81ad6265SDimitry Andric applyBasicType(); 80*81ad6265SDimitry Andric applyModifier(prototype); 81*81ad6265SDimitry Andric Valid = verifyType(); 82*81ad6265SDimitry Andric if (Valid) { 83*81ad6265SDimitry Andric initBuiltinStr(); 84*81ad6265SDimitry Andric initTypeStr(); 85*81ad6265SDimitry Andric if (isVector()) { 86*81ad6265SDimitry Andric initClangBuiltinStr(); 87*81ad6265SDimitry Andric } 88*81ad6265SDimitry Andric } 89*81ad6265SDimitry Andric } 90*81ad6265SDimitry Andric 91*81ad6265SDimitry Andric // clang-format off 92*81ad6265SDimitry Andric // boolean type are encoded the ratio of n (SEW/LMUL) 93*81ad6265SDimitry Andric // SEW/LMUL | 1 | 2 | 4 | 8 | 16 | 32 | 64 94*81ad6265SDimitry Andric // c type | vbool64_t | vbool32_t | vbool16_t | vbool8_t | vbool4_t | vbool2_t | vbool1_t 95*81ad6265SDimitry Andric // IR type | nxv1i1 | nxv2i1 | nxv4i1 | nxv8i1 | nxv16i1 | nxv32i1 | nxv64i1 96*81ad6265SDimitry Andric 97*81ad6265SDimitry Andric // type\lmul | 1/8 | 1/4 | 1/2 | 1 | 2 | 4 | 8 98*81ad6265SDimitry Andric // -------- |------ | -------- | ------- | ------- | -------- | -------- | -------- 99*81ad6265SDimitry Andric // i64 | N/A | N/A | N/A | nxv1i64 | nxv2i64 | nxv4i64 | nxv8i64 100*81ad6265SDimitry Andric // i32 | N/A | N/A | nxv1i32 | nxv2i32 | nxv4i32 | nxv8i32 | nxv16i32 101*81ad6265SDimitry Andric // i16 | N/A | nxv1i16 | nxv2i16 | nxv4i16 | nxv8i16 | nxv16i16 | nxv32i16 102*81ad6265SDimitry Andric // i8 | nxv1i8 | nxv2i8 | nxv4i8 | nxv8i8 | nxv16i8 | nxv32i8 | nxv64i8 103*81ad6265SDimitry Andric // double | N/A | N/A | N/A | nxv1f64 | nxv2f64 | nxv4f64 | nxv8f64 104*81ad6265SDimitry Andric // float | N/A | N/A | nxv1f32 | nxv2f32 | nxv4f32 | nxv8f32 | nxv16f32 105*81ad6265SDimitry Andric // half | N/A | nxv1f16 | nxv2f16 | nxv4f16 | nxv8f16 | nxv16f16 | nxv32f16 106*81ad6265SDimitry Andric // clang-format on 107*81ad6265SDimitry Andric 108*81ad6265SDimitry Andric bool RVVType::verifyType() const { 109*81ad6265SDimitry Andric if (ScalarType == Invalid) 110*81ad6265SDimitry Andric return false; 111*81ad6265SDimitry Andric if (isScalar()) 112*81ad6265SDimitry Andric return true; 113*81ad6265SDimitry Andric if (!Scale) 114*81ad6265SDimitry Andric return false; 115*81ad6265SDimitry Andric if (isFloat() && ElementBitwidth == 8) 116*81ad6265SDimitry Andric return false; 117*81ad6265SDimitry Andric unsigned V = Scale.getValue(); 118*81ad6265SDimitry Andric switch (ElementBitwidth) { 119*81ad6265SDimitry Andric case 1: 120*81ad6265SDimitry Andric case 8: 121*81ad6265SDimitry Andric // Check Scale is 1,2,4,8,16,32,64 122*81ad6265SDimitry Andric return (V <= 64 && isPowerOf2_32(V)); 123*81ad6265SDimitry Andric case 16: 124*81ad6265SDimitry Andric // Check Scale is 1,2,4,8,16,32 125*81ad6265SDimitry Andric return (V <= 32 && isPowerOf2_32(V)); 126*81ad6265SDimitry Andric case 32: 127*81ad6265SDimitry Andric // Check Scale is 1,2,4,8,16 128*81ad6265SDimitry Andric return (V <= 16 && isPowerOf2_32(V)); 129*81ad6265SDimitry Andric case 64: 130*81ad6265SDimitry Andric // Check Scale is 1,2,4,8 131*81ad6265SDimitry Andric return (V <= 8 && isPowerOf2_32(V)); 132*81ad6265SDimitry Andric } 133*81ad6265SDimitry Andric return false; 134*81ad6265SDimitry Andric } 135*81ad6265SDimitry Andric 136*81ad6265SDimitry Andric void RVVType::initBuiltinStr() { 137*81ad6265SDimitry Andric assert(isValid() && "RVVType is invalid"); 138*81ad6265SDimitry Andric switch (ScalarType) { 139*81ad6265SDimitry Andric case ScalarTypeKind::Void: 140*81ad6265SDimitry Andric BuiltinStr = "v"; 141*81ad6265SDimitry Andric return; 142*81ad6265SDimitry Andric case ScalarTypeKind::Size_t: 143*81ad6265SDimitry Andric BuiltinStr = "z"; 144*81ad6265SDimitry Andric if (IsImmediate) 145*81ad6265SDimitry Andric BuiltinStr = "I" + BuiltinStr; 146*81ad6265SDimitry Andric if (IsPointer) 147*81ad6265SDimitry Andric BuiltinStr += "*"; 148*81ad6265SDimitry Andric return; 149*81ad6265SDimitry Andric case ScalarTypeKind::Ptrdiff_t: 150*81ad6265SDimitry Andric BuiltinStr = "Y"; 151*81ad6265SDimitry Andric return; 152*81ad6265SDimitry Andric case ScalarTypeKind::UnsignedLong: 153*81ad6265SDimitry Andric BuiltinStr = "ULi"; 154*81ad6265SDimitry Andric return; 155*81ad6265SDimitry Andric case ScalarTypeKind::SignedLong: 156*81ad6265SDimitry Andric BuiltinStr = "Li"; 157*81ad6265SDimitry Andric return; 158*81ad6265SDimitry Andric case ScalarTypeKind::Boolean: 159*81ad6265SDimitry Andric assert(ElementBitwidth == 1); 160*81ad6265SDimitry Andric BuiltinStr += "b"; 161*81ad6265SDimitry Andric break; 162*81ad6265SDimitry Andric case ScalarTypeKind::SignedInteger: 163*81ad6265SDimitry Andric case ScalarTypeKind::UnsignedInteger: 164*81ad6265SDimitry Andric switch (ElementBitwidth) { 165*81ad6265SDimitry Andric case 8: 166*81ad6265SDimitry Andric BuiltinStr += "c"; 167*81ad6265SDimitry Andric break; 168*81ad6265SDimitry Andric case 16: 169*81ad6265SDimitry Andric BuiltinStr += "s"; 170*81ad6265SDimitry Andric break; 171*81ad6265SDimitry Andric case 32: 172*81ad6265SDimitry Andric BuiltinStr += "i"; 173*81ad6265SDimitry Andric break; 174*81ad6265SDimitry Andric case 64: 175*81ad6265SDimitry Andric BuiltinStr += "Wi"; 176*81ad6265SDimitry Andric break; 177*81ad6265SDimitry Andric default: 178*81ad6265SDimitry Andric llvm_unreachable("Unhandled ElementBitwidth!"); 179*81ad6265SDimitry Andric } 180*81ad6265SDimitry Andric if (isSignedInteger()) 181*81ad6265SDimitry Andric BuiltinStr = "S" + BuiltinStr; 182*81ad6265SDimitry Andric else 183*81ad6265SDimitry Andric BuiltinStr = "U" + BuiltinStr; 184*81ad6265SDimitry Andric break; 185*81ad6265SDimitry Andric case ScalarTypeKind::Float: 186*81ad6265SDimitry Andric switch (ElementBitwidth) { 187*81ad6265SDimitry Andric case 16: 188*81ad6265SDimitry Andric BuiltinStr += "x"; 189*81ad6265SDimitry Andric break; 190*81ad6265SDimitry Andric case 32: 191*81ad6265SDimitry Andric BuiltinStr += "f"; 192*81ad6265SDimitry Andric break; 193*81ad6265SDimitry Andric case 64: 194*81ad6265SDimitry Andric BuiltinStr += "d"; 195*81ad6265SDimitry Andric break; 196*81ad6265SDimitry Andric default: 197*81ad6265SDimitry Andric llvm_unreachable("Unhandled ElementBitwidth!"); 198*81ad6265SDimitry Andric } 199*81ad6265SDimitry Andric break; 200*81ad6265SDimitry Andric default: 201*81ad6265SDimitry Andric llvm_unreachable("ScalarType is invalid!"); 202*81ad6265SDimitry Andric } 203*81ad6265SDimitry Andric if (IsImmediate) 204*81ad6265SDimitry Andric BuiltinStr = "I" + BuiltinStr; 205*81ad6265SDimitry Andric if (isScalar()) { 206*81ad6265SDimitry Andric if (IsConstant) 207*81ad6265SDimitry Andric BuiltinStr += "C"; 208*81ad6265SDimitry Andric if (IsPointer) 209*81ad6265SDimitry Andric BuiltinStr += "*"; 210*81ad6265SDimitry Andric return; 211*81ad6265SDimitry Andric } 212*81ad6265SDimitry Andric BuiltinStr = "q" + utostr(*Scale) + BuiltinStr; 213*81ad6265SDimitry Andric // Pointer to vector types. Defined for segment load intrinsics. 214*81ad6265SDimitry Andric // segment load intrinsics have pointer type arguments to store the loaded 215*81ad6265SDimitry Andric // vector values. 216*81ad6265SDimitry Andric if (IsPointer) 217*81ad6265SDimitry Andric BuiltinStr += "*"; 218*81ad6265SDimitry Andric } 219*81ad6265SDimitry Andric 220*81ad6265SDimitry Andric void RVVType::initClangBuiltinStr() { 221*81ad6265SDimitry Andric assert(isValid() && "RVVType is invalid"); 222*81ad6265SDimitry Andric assert(isVector() && "Handle Vector type only"); 223*81ad6265SDimitry Andric 224*81ad6265SDimitry Andric ClangBuiltinStr = "__rvv_"; 225*81ad6265SDimitry Andric switch (ScalarType) { 226*81ad6265SDimitry Andric case ScalarTypeKind::Boolean: 227*81ad6265SDimitry Andric ClangBuiltinStr += "bool" + utostr(64 / *Scale) + "_t"; 228*81ad6265SDimitry Andric return; 229*81ad6265SDimitry Andric case ScalarTypeKind::Float: 230*81ad6265SDimitry Andric ClangBuiltinStr += "float"; 231*81ad6265SDimitry Andric break; 232*81ad6265SDimitry Andric case ScalarTypeKind::SignedInteger: 233*81ad6265SDimitry Andric ClangBuiltinStr += "int"; 234*81ad6265SDimitry Andric break; 235*81ad6265SDimitry Andric case ScalarTypeKind::UnsignedInteger: 236*81ad6265SDimitry Andric ClangBuiltinStr += "uint"; 237*81ad6265SDimitry Andric break; 238*81ad6265SDimitry Andric default: 239*81ad6265SDimitry Andric llvm_unreachable("ScalarTypeKind is invalid"); 240*81ad6265SDimitry Andric } 241*81ad6265SDimitry Andric ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.str() + "_t"; 242*81ad6265SDimitry Andric } 243*81ad6265SDimitry Andric 244*81ad6265SDimitry Andric void RVVType::initTypeStr() { 245*81ad6265SDimitry Andric assert(isValid() && "RVVType is invalid"); 246*81ad6265SDimitry Andric 247*81ad6265SDimitry Andric if (IsConstant) 248*81ad6265SDimitry Andric Str += "const "; 249*81ad6265SDimitry Andric 250*81ad6265SDimitry Andric auto getTypeString = [&](StringRef TypeStr) { 251*81ad6265SDimitry Andric if (isScalar()) 252*81ad6265SDimitry Andric return Twine(TypeStr + Twine(ElementBitwidth) + "_t").str(); 253*81ad6265SDimitry Andric return Twine("v" + TypeStr + Twine(ElementBitwidth) + LMUL.str() + "_t") 254*81ad6265SDimitry Andric .str(); 255*81ad6265SDimitry Andric }; 256*81ad6265SDimitry Andric 257*81ad6265SDimitry Andric switch (ScalarType) { 258*81ad6265SDimitry Andric case ScalarTypeKind::Void: 259*81ad6265SDimitry Andric Str = "void"; 260*81ad6265SDimitry Andric return; 261*81ad6265SDimitry Andric case ScalarTypeKind::Size_t: 262*81ad6265SDimitry Andric Str = "size_t"; 263*81ad6265SDimitry Andric if (IsPointer) 264*81ad6265SDimitry Andric Str += " *"; 265*81ad6265SDimitry Andric return; 266*81ad6265SDimitry Andric case ScalarTypeKind::Ptrdiff_t: 267*81ad6265SDimitry Andric Str = "ptrdiff_t"; 268*81ad6265SDimitry Andric return; 269*81ad6265SDimitry Andric case ScalarTypeKind::UnsignedLong: 270*81ad6265SDimitry Andric Str = "unsigned long"; 271*81ad6265SDimitry Andric return; 272*81ad6265SDimitry Andric case ScalarTypeKind::SignedLong: 273*81ad6265SDimitry Andric Str = "long"; 274*81ad6265SDimitry Andric return; 275*81ad6265SDimitry Andric case ScalarTypeKind::Boolean: 276*81ad6265SDimitry Andric if (isScalar()) 277*81ad6265SDimitry Andric Str += "bool"; 278*81ad6265SDimitry Andric else 279*81ad6265SDimitry Andric // Vector bool is special case, the formulate is 280*81ad6265SDimitry Andric // `vbool<N>_t = MVT::nxv<64/N>i1` ex. vbool16_t = MVT::4i1 281*81ad6265SDimitry Andric Str += "vbool" + utostr(64 / *Scale) + "_t"; 282*81ad6265SDimitry Andric break; 283*81ad6265SDimitry Andric case ScalarTypeKind::Float: 284*81ad6265SDimitry Andric if (isScalar()) { 285*81ad6265SDimitry Andric if (ElementBitwidth == 64) 286*81ad6265SDimitry Andric Str += "double"; 287*81ad6265SDimitry Andric else if (ElementBitwidth == 32) 288*81ad6265SDimitry Andric Str += "float"; 289*81ad6265SDimitry Andric else if (ElementBitwidth == 16) 290*81ad6265SDimitry Andric Str += "_Float16"; 291*81ad6265SDimitry Andric else 292*81ad6265SDimitry Andric llvm_unreachable("Unhandled floating type."); 293*81ad6265SDimitry Andric } else 294*81ad6265SDimitry Andric Str += getTypeString("float"); 295*81ad6265SDimitry Andric break; 296*81ad6265SDimitry Andric case ScalarTypeKind::SignedInteger: 297*81ad6265SDimitry Andric Str += getTypeString("int"); 298*81ad6265SDimitry Andric break; 299*81ad6265SDimitry Andric case ScalarTypeKind::UnsignedInteger: 300*81ad6265SDimitry Andric Str += getTypeString("uint"); 301*81ad6265SDimitry Andric break; 302*81ad6265SDimitry Andric default: 303*81ad6265SDimitry Andric llvm_unreachable("ScalarType is invalid!"); 304*81ad6265SDimitry Andric } 305*81ad6265SDimitry Andric if (IsPointer) 306*81ad6265SDimitry Andric Str += " *"; 307*81ad6265SDimitry Andric } 308*81ad6265SDimitry Andric 309*81ad6265SDimitry Andric void RVVType::initShortStr() { 310*81ad6265SDimitry Andric switch (ScalarType) { 311*81ad6265SDimitry Andric case ScalarTypeKind::Boolean: 312*81ad6265SDimitry Andric assert(isVector()); 313*81ad6265SDimitry Andric ShortStr = "b" + utostr(64 / *Scale); 314*81ad6265SDimitry Andric return; 315*81ad6265SDimitry Andric case ScalarTypeKind::Float: 316*81ad6265SDimitry Andric ShortStr = "f" + utostr(ElementBitwidth); 317*81ad6265SDimitry Andric break; 318*81ad6265SDimitry Andric case ScalarTypeKind::SignedInteger: 319*81ad6265SDimitry Andric ShortStr = "i" + utostr(ElementBitwidth); 320*81ad6265SDimitry Andric break; 321*81ad6265SDimitry Andric case ScalarTypeKind::UnsignedInteger: 322*81ad6265SDimitry Andric ShortStr = "u" + utostr(ElementBitwidth); 323*81ad6265SDimitry Andric break; 324*81ad6265SDimitry Andric default: 325*81ad6265SDimitry Andric llvm_unreachable("Unhandled case!"); 326*81ad6265SDimitry Andric } 327*81ad6265SDimitry Andric if (isVector()) 328*81ad6265SDimitry Andric ShortStr += LMUL.str(); 329*81ad6265SDimitry Andric } 330*81ad6265SDimitry Andric 331*81ad6265SDimitry Andric void RVVType::applyBasicType() { 332*81ad6265SDimitry Andric switch (BT) { 333*81ad6265SDimitry Andric case BasicType::Int8: 334*81ad6265SDimitry Andric ElementBitwidth = 8; 335*81ad6265SDimitry Andric ScalarType = ScalarTypeKind::SignedInteger; 336*81ad6265SDimitry Andric break; 337*81ad6265SDimitry Andric case BasicType::Int16: 338*81ad6265SDimitry Andric ElementBitwidth = 16; 339*81ad6265SDimitry Andric ScalarType = ScalarTypeKind::SignedInteger; 340*81ad6265SDimitry Andric break; 341*81ad6265SDimitry Andric case BasicType::Int32: 342*81ad6265SDimitry Andric ElementBitwidth = 32; 343*81ad6265SDimitry Andric ScalarType = ScalarTypeKind::SignedInteger; 344*81ad6265SDimitry Andric break; 345*81ad6265SDimitry Andric case BasicType::Int64: 346*81ad6265SDimitry Andric ElementBitwidth = 64; 347*81ad6265SDimitry Andric ScalarType = ScalarTypeKind::SignedInteger; 348*81ad6265SDimitry Andric break; 349*81ad6265SDimitry Andric case BasicType::Float16: 350*81ad6265SDimitry Andric ElementBitwidth = 16; 351*81ad6265SDimitry Andric ScalarType = ScalarTypeKind::Float; 352*81ad6265SDimitry Andric break; 353*81ad6265SDimitry Andric case BasicType::Float32: 354*81ad6265SDimitry Andric ElementBitwidth = 32; 355*81ad6265SDimitry Andric ScalarType = ScalarTypeKind::Float; 356*81ad6265SDimitry Andric break; 357*81ad6265SDimitry Andric case BasicType::Float64: 358*81ad6265SDimitry Andric ElementBitwidth = 64; 359*81ad6265SDimitry Andric ScalarType = ScalarTypeKind::Float; 360*81ad6265SDimitry Andric break; 361*81ad6265SDimitry Andric default: 362*81ad6265SDimitry Andric llvm_unreachable("Unhandled type code!"); 363*81ad6265SDimitry Andric } 364*81ad6265SDimitry Andric assert(ElementBitwidth != 0 && "Bad element bitwidth!"); 365*81ad6265SDimitry Andric } 366*81ad6265SDimitry Andric 367*81ad6265SDimitry Andric Optional<PrototypeDescriptor> PrototypeDescriptor::parsePrototypeDescriptor( 368*81ad6265SDimitry Andric llvm::StringRef PrototypeDescriptorStr) { 369*81ad6265SDimitry Andric PrototypeDescriptor PD; 370*81ad6265SDimitry Andric BaseTypeModifier PT = BaseTypeModifier::Invalid; 371*81ad6265SDimitry Andric VectorTypeModifier VTM = VectorTypeModifier::NoModifier; 372*81ad6265SDimitry Andric 373*81ad6265SDimitry Andric if (PrototypeDescriptorStr.empty()) 374*81ad6265SDimitry Andric return PD; 375*81ad6265SDimitry Andric 376*81ad6265SDimitry Andric // Handle base type modifier 377*81ad6265SDimitry Andric auto PType = PrototypeDescriptorStr.back(); 378*81ad6265SDimitry Andric switch (PType) { 379*81ad6265SDimitry Andric case 'e': 380*81ad6265SDimitry Andric PT = BaseTypeModifier::Scalar; 381*81ad6265SDimitry Andric break; 382*81ad6265SDimitry Andric case 'v': 383*81ad6265SDimitry Andric PT = BaseTypeModifier::Vector; 384*81ad6265SDimitry Andric break; 385*81ad6265SDimitry Andric case 'w': 386*81ad6265SDimitry Andric PT = BaseTypeModifier::Vector; 387*81ad6265SDimitry Andric VTM = VectorTypeModifier::Widening2XVector; 388*81ad6265SDimitry Andric break; 389*81ad6265SDimitry Andric case 'q': 390*81ad6265SDimitry Andric PT = BaseTypeModifier::Vector; 391*81ad6265SDimitry Andric VTM = VectorTypeModifier::Widening4XVector; 392*81ad6265SDimitry Andric break; 393*81ad6265SDimitry Andric case 'o': 394*81ad6265SDimitry Andric PT = BaseTypeModifier::Vector; 395*81ad6265SDimitry Andric VTM = VectorTypeModifier::Widening8XVector; 396*81ad6265SDimitry Andric break; 397*81ad6265SDimitry Andric case 'm': 398*81ad6265SDimitry Andric PT = BaseTypeModifier::Vector; 399*81ad6265SDimitry Andric VTM = VectorTypeModifier::MaskVector; 400*81ad6265SDimitry Andric break; 401*81ad6265SDimitry Andric case '0': 402*81ad6265SDimitry Andric PT = BaseTypeModifier::Void; 403*81ad6265SDimitry Andric break; 404*81ad6265SDimitry Andric case 'z': 405*81ad6265SDimitry Andric PT = BaseTypeModifier::SizeT; 406*81ad6265SDimitry Andric break; 407*81ad6265SDimitry Andric case 't': 408*81ad6265SDimitry Andric PT = BaseTypeModifier::Ptrdiff; 409*81ad6265SDimitry Andric break; 410*81ad6265SDimitry Andric case 'u': 411*81ad6265SDimitry Andric PT = BaseTypeModifier::UnsignedLong; 412*81ad6265SDimitry Andric break; 413*81ad6265SDimitry Andric case 'l': 414*81ad6265SDimitry Andric PT = BaseTypeModifier::SignedLong; 415*81ad6265SDimitry Andric break; 416*81ad6265SDimitry Andric default: 417*81ad6265SDimitry Andric llvm_unreachable("Illegal primitive type transformers!"); 418*81ad6265SDimitry Andric } 419*81ad6265SDimitry Andric PD.PT = static_cast<uint8_t>(PT); 420*81ad6265SDimitry Andric PrototypeDescriptorStr = PrototypeDescriptorStr.drop_back(); 421*81ad6265SDimitry Andric 422*81ad6265SDimitry Andric // Compute the vector type transformers, it can only appear one time. 423*81ad6265SDimitry Andric if (PrototypeDescriptorStr.startswith("(")) { 424*81ad6265SDimitry Andric assert(VTM == VectorTypeModifier::NoModifier && 425*81ad6265SDimitry Andric "VectorTypeModifier should only have one modifier"); 426*81ad6265SDimitry Andric size_t Idx = PrototypeDescriptorStr.find(')'); 427*81ad6265SDimitry Andric assert(Idx != StringRef::npos); 428*81ad6265SDimitry Andric StringRef ComplexType = PrototypeDescriptorStr.slice(1, Idx); 429*81ad6265SDimitry Andric PrototypeDescriptorStr = PrototypeDescriptorStr.drop_front(Idx + 1); 430*81ad6265SDimitry Andric assert(!PrototypeDescriptorStr.contains('(') && 431*81ad6265SDimitry Andric "Only allow one vector type modifier"); 432*81ad6265SDimitry Andric 433*81ad6265SDimitry Andric auto ComplexTT = ComplexType.split(":"); 434*81ad6265SDimitry Andric if (ComplexTT.first == "Log2EEW") { 435*81ad6265SDimitry Andric uint32_t Log2EEW; 436*81ad6265SDimitry Andric if (ComplexTT.second.getAsInteger(10, Log2EEW)) { 437*81ad6265SDimitry Andric llvm_unreachable("Invalid Log2EEW value!"); 438*81ad6265SDimitry Andric return None; 439*81ad6265SDimitry Andric } 440*81ad6265SDimitry Andric switch (Log2EEW) { 441*81ad6265SDimitry Andric case 3: 442*81ad6265SDimitry Andric VTM = VectorTypeModifier::Log2EEW3; 443*81ad6265SDimitry Andric break; 444*81ad6265SDimitry Andric case 4: 445*81ad6265SDimitry Andric VTM = VectorTypeModifier::Log2EEW4; 446*81ad6265SDimitry Andric break; 447*81ad6265SDimitry Andric case 5: 448*81ad6265SDimitry Andric VTM = VectorTypeModifier::Log2EEW5; 449*81ad6265SDimitry Andric break; 450*81ad6265SDimitry Andric case 6: 451*81ad6265SDimitry Andric VTM = VectorTypeModifier::Log2EEW6; 452*81ad6265SDimitry Andric break; 453*81ad6265SDimitry Andric default: 454*81ad6265SDimitry Andric llvm_unreachable("Invalid Log2EEW value, should be [3-6]"); 455*81ad6265SDimitry Andric return None; 456*81ad6265SDimitry Andric } 457*81ad6265SDimitry Andric } else if (ComplexTT.first == "FixedSEW") { 458*81ad6265SDimitry Andric uint32_t NewSEW; 459*81ad6265SDimitry Andric if (ComplexTT.second.getAsInteger(10, NewSEW)) { 460*81ad6265SDimitry Andric llvm_unreachable("Invalid FixedSEW value!"); 461*81ad6265SDimitry Andric return None; 462*81ad6265SDimitry Andric } 463*81ad6265SDimitry Andric switch (NewSEW) { 464*81ad6265SDimitry Andric case 8: 465*81ad6265SDimitry Andric VTM = VectorTypeModifier::FixedSEW8; 466*81ad6265SDimitry Andric break; 467*81ad6265SDimitry Andric case 16: 468*81ad6265SDimitry Andric VTM = VectorTypeModifier::FixedSEW16; 469*81ad6265SDimitry Andric break; 470*81ad6265SDimitry Andric case 32: 471*81ad6265SDimitry Andric VTM = VectorTypeModifier::FixedSEW32; 472*81ad6265SDimitry Andric break; 473*81ad6265SDimitry Andric case 64: 474*81ad6265SDimitry Andric VTM = VectorTypeModifier::FixedSEW64; 475*81ad6265SDimitry Andric break; 476*81ad6265SDimitry Andric default: 477*81ad6265SDimitry Andric llvm_unreachable("Invalid FixedSEW value, should be 8, 16, 32 or 64"); 478*81ad6265SDimitry Andric return None; 479*81ad6265SDimitry Andric } 480*81ad6265SDimitry Andric } else if (ComplexTT.first == "LFixedLog2LMUL") { 481*81ad6265SDimitry Andric int32_t Log2LMUL; 482*81ad6265SDimitry Andric if (ComplexTT.second.getAsInteger(10, Log2LMUL)) { 483*81ad6265SDimitry Andric llvm_unreachable("Invalid LFixedLog2LMUL value!"); 484*81ad6265SDimitry Andric return None; 485*81ad6265SDimitry Andric } 486*81ad6265SDimitry Andric switch (Log2LMUL) { 487*81ad6265SDimitry Andric case -3: 488*81ad6265SDimitry Andric VTM = VectorTypeModifier::LFixedLog2LMULN3; 489*81ad6265SDimitry Andric break; 490*81ad6265SDimitry Andric case -2: 491*81ad6265SDimitry Andric VTM = VectorTypeModifier::LFixedLog2LMULN2; 492*81ad6265SDimitry Andric break; 493*81ad6265SDimitry Andric case -1: 494*81ad6265SDimitry Andric VTM = VectorTypeModifier::LFixedLog2LMULN1; 495*81ad6265SDimitry Andric break; 496*81ad6265SDimitry Andric case 0: 497*81ad6265SDimitry Andric VTM = VectorTypeModifier::LFixedLog2LMUL0; 498*81ad6265SDimitry Andric break; 499*81ad6265SDimitry Andric case 1: 500*81ad6265SDimitry Andric VTM = VectorTypeModifier::LFixedLog2LMUL1; 501*81ad6265SDimitry Andric break; 502*81ad6265SDimitry Andric case 2: 503*81ad6265SDimitry Andric VTM = VectorTypeModifier::LFixedLog2LMUL2; 504*81ad6265SDimitry Andric break; 505*81ad6265SDimitry Andric case 3: 506*81ad6265SDimitry Andric VTM = VectorTypeModifier::LFixedLog2LMUL3; 507*81ad6265SDimitry Andric break; 508*81ad6265SDimitry Andric default: 509*81ad6265SDimitry Andric llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]"); 510*81ad6265SDimitry Andric return None; 511*81ad6265SDimitry Andric } 512*81ad6265SDimitry Andric } else if (ComplexTT.first == "SFixedLog2LMUL") { 513*81ad6265SDimitry Andric int32_t Log2LMUL; 514*81ad6265SDimitry Andric if (ComplexTT.second.getAsInteger(10, Log2LMUL)) { 515*81ad6265SDimitry Andric llvm_unreachable("Invalid SFixedLog2LMUL value!"); 516*81ad6265SDimitry Andric return None; 517*81ad6265SDimitry Andric } 518*81ad6265SDimitry Andric switch (Log2LMUL) { 519*81ad6265SDimitry Andric case -3: 520*81ad6265SDimitry Andric VTM = VectorTypeModifier::SFixedLog2LMULN3; 521*81ad6265SDimitry Andric break; 522*81ad6265SDimitry Andric case -2: 523*81ad6265SDimitry Andric VTM = VectorTypeModifier::SFixedLog2LMULN2; 524*81ad6265SDimitry Andric break; 525*81ad6265SDimitry Andric case -1: 526*81ad6265SDimitry Andric VTM = VectorTypeModifier::SFixedLog2LMULN1; 527*81ad6265SDimitry Andric break; 528*81ad6265SDimitry Andric case 0: 529*81ad6265SDimitry Andric VTM = VectorTypeModifier::SFixedLog2LMUL0; 530*81ad6265SDimitry Andric break; 531*81ad6265SDimitry Andric case 1: 532*81ad6265SDimitry Andric VTM = VectorTypeModifier::SFixedLog2LMUL1; 533*81ad6265SDimitry Andric break; 534*81ad6265SDimitry Andric case 2: 535*81ad6265SDimitry Andric VTM = VectorTypeModifier::SFixedLog2LMUL2; 536*81ad6265SDimitry Andric break; 537*81ad6265SDimitry Andric case 3: 538*81ad6265SDimitry Andric VTM = VectorTypeModifier::SFixedLog2LMUL3; 539*81ad6265SDimitry Andric break; 540*81ad6265SDimitry Andric default: 541*81ad6265SDimitry Andric llvm_unreachable("Invalid LFixedLog2LMUL value, should be [-3, 3]"); 542*81ad6265SDimitry Andric return None; 543*81ad6265SDimitry Andric } 544*81ad6265SDimitry Andric 545*81ad6265SDimitry Andric } else { 546*81ad6265SDimitry Andric llvm_unreachable("Illegal complex type transformers!"); 547*81ad6265SDimitry Andric } 548*81ad6265SDimitry Andric } 549*81ad6265SDimitry Andric PD.VTM = static_cast<uint8_t>(VTM); 550*81ad6265SDimitry Andric 551*81ad6265SDimitry Andric // Compute the remain type transformers 552*81ad6265SDimitry Andric TypeModifier TM = TypeModifier::NoModifier; 553*81ad6265SDimitry Andric for (char I : PrototypeDescriptorStr) { 554*81ad6265SDimitry Andric switch (I) { 555*81ad6265SDimitry Andric case 'P': 556*81ad6265SDimitry Andric if ((TM & TypeModifier::Const) == TypeModifier::Const) 557*81ad6265SDimitry Andric llvm_unreachable("'P' transformer cannot be used after 'C'"); 558*81ad6265SDimitry Andric if ((TM & TypeModifier::Pointer) == TypeModifier::Pointer) 559*81ad6265SDimitry Andric llvm_unreachable("'P' transformer cannot be used twice"); 560*81ad6265SDimitry Andric TM |= TypeModifier::Pointer; 561*81ad6265SDimitry Andric break; 562*81ad6265SDimitry Andric case 'C': 563*81ad6265SDimitry Andric TM |= TypeModifier::Const; 564*81ad6265SDimitry Andric break; 565*81ad6265SDimitry Andric case 'K': 566*81ad6265SDimitry Andric TM |= TypeModifier::Immediate; 567*81ad6265SDimitry Andric break; 568*81ad6265SDimitry Andric case 'U': 569*81ad6265SDimitry Andric TM |= TypeModifier::UnsignedInteger; 570*81ad6265SDimitry Andric break; 571*81ad6265SDimitry Andric case 'I': 572*81ad6265SDimitry Andric TM |= TypeModifier::SignedInteger; 573*81ad6265SDimitry Andric break; 574*81ad6265SDimitry Andric case 'F': 575*81ad6265SDimitry Andric TM |= TypeModifier::Float; 576*81ad6265SDimitry Andric break; 577*81ad6265SDimitry Andric case 'S': 578*81ad6265SDimitry Andric TM |= TypeModifier::LMUL1; 579*81ad6265SDimitry Andric break; 580*81ad6265SDimitry Andric default: 581*81ad6265SDimitry Andric llvm_unreachable("Illegal non-primitive type transformer!"); 582*81ad6265SDimitry Andric } 583*81ad6265SDimitry Andric } 584*81ad6265SDimitry Andric PD.TM = static_cast<uint8_t>(TM); 585*81ad6265SDimitry Andric 586*81ad6265SDimitry Andric return PD; 587*81ad6265SDimitry Andric } 588*81ad6265SDimitry Andric 589*81ad6265SDimitry Andric void RVVType::applyModifier(const PrototypeDescriptor &Transformer) { 590*81ad6265SDimitry Andric // Handle primitive type transformer 591*81ad6265SDimitry Andric switch (static_cast<BaseTypeModifier>(Transformer.PT)) { 592*81ad6265SDimitry Andric case BaseTypeModifier::Scalar: 593*81ad6265SDimitry Andric Scale = 0; 594*81ad6265SDimitry Andric break; 595*81ad6265SDimitry Andric case BaseTypeModifier::Vector: 596*81ad6265SDimitry Andric Scale = LMUL.getScale(ElementBitwidth); 597*81ad6265SDimitry Andric break; 598*81ad6265SDimitry Andric case BaseTypeModifier::Void: 599*81ad6265SDimitry Andric ScalarType = ScalarTypeKind::Void; 600*81ad6265SDimitry Andric break; 601*81ad6265SDimitry Andric case BaseTypeModifier::SizeT: 602*81ad6265SDimitry Andric ScalarType = ScalarTypeKind::Size_t; 603*81ad6265SDimitry Andric break; 604*81ad6265SDimitry Andric case BaseTypeModifier::Ptrdiff: 605*81ad6265SDimitry Andric ScalarType = ScalarTypeKind::Ptrdiff_t; 606*81ad6265SDimitry Andric break; 607*81ad6265SDimitry Andric case BaseTypeModifier::UnsignedLong: 608*81ad6265SDimitry Andric ScalarType = ScalarTypeKind::UnsignedLong; 609*81ad6265SDimitry Andric break; 610*81ad6265SDimitry Andric case BaseTypeModifier::SignedLong: 611*81ad6265SDimitry Andric ScalarType = ScalarTypeKind::SignedLong; 612*81ad6265SDimitry Andric break; 613*81ad6265SDimitry Andric case BaseTypeModifier::Invalid: 614*81ad6265SDimitry Andric ScalarType = ScalarTypeKind::Invalid; 615*81ad6265SDimitry Andric return; 616*81ad6265SDimitry Andric } 617*81ad6265SDimitry Andric 618*81ad6265SDimitry Andric switch (static_cast<VectorTypeModifier>(Transformer.VTM)) { 619*81ad6265SDimitry Andric case VectorTypeModifier::Widening2XVector: 620*81ad6265SDimitry Andric ElementBitwidth *= 2; 621*81ad6265SDimitry Andric LMUL.MulLog2LMUL(1); 622*81ad6265SDimitry Andric Scale = LMUL.getScale(ElementBitwidth); 623*81ad6265SDimitry Andric break; 624*81ad6265SDimitry Andric case VectorTypeModifier::Widening4XVector: 625*81ad6265SDimitry Andric ElementBitwidth *= 4; 626*81ad6265SDimitry Andric LMUL.MulLog2LMUL(2); 627*81ad6265SDimitry Andric Scale = LMUL.getScale(ElementBitwidth); 628*81ad6265SDimitry Andric break; 629*81ad6265SDimitry Andric case VectorTypeModifier::Widening8XVector: 630*81ad6265SDimitry Andric ElementBitwidth *= 8; 631*81ad6265SDimitry Andric LMUL.MulLog2LMUL(3); 632*81ad6265SDimitry Andric Scale = LMUL.getScale(ElementBitwidth); 633*81ad6265SDimitry Andric break; 634*81ad6265SDimitry Andric case VectorTypeModifier::MaskVector: 635*81ad6265SDimitry Andric ScalarType = ScalarTypeKind::Boolean; 636*81ad6265SDimitry Andric Scale = LMUL.getScale(ElementBitwidth); 637*81ad6265SDimitry Andric ElementBitwidth = 1; 638*81ad6265SDimitry Andric break; 639*81ad6265SDimitry Andric case VectorTypeModifier::Log2EEW3: 640*81ad6265SDimitry Andric applyLog2EEW(3); 641*81ad6265SDimitry Andric break; 642*81ad6265SDimitry Andric case VectorTypeModifier::Log2EEW4: 643*81ad6265SDimitry Andric applyLog2EEW(4); 644*81ad6265SDimitry Andric break; 645*81ad6265SDimitry Andric case VectorTypeModifier::Log2EEW5: 646*81ad6265SDimitry Andric applyLog2EEW(5); 647*81ad6265SDimitry Andric break; 648*81ad6265SDimitry Andric case VectorTypeModifier::Log2EEW6: 649*81ad6265SDimitry Andric applyLog2EEW(6); 650*81ad6265SDimitry Andric break; 651*81ad6265SDimitry Andric case VectorTypeModifier::FixedSEW8: 652*81ad6265SDimitry Andric applyFixedSEW(8); 653*81ad6265SDimitry Andric break; 654*81ad6265SDimitry Andric case VectorTypeModifier::FixedSEW16: 655*81ad6265SDimitry Andric applyFixedSEW(16); 656*81ad6265SDimitry Andric break; 657*81ad6265SDimitry Andric case VectorTypeModifier::FixedSEW32: 658*81ad6265SDimitry Andric applyFixedSEW(32); 659*81ad6265SDimitry Andric break; 660*81ad6265SDimitry Andric case VectorTypeModifier::FixedSEW64: 661*81ad6265SDimitry Andric applyFixedSEW(64); 662*81ad6265SDimitry Andric break; 663*81ad6265SDimitry Andric case VectorTypeModifier::LFixedLog2LMULN3: 664*81ad6265SDimitry Andric applyFixedLog2LMUL(-3, FixedLMULType::LargerThan); 665*81ad6265SDimitry Andric break; 666*81ad6265SDimitry Andric case VectorTypeModifier::LFixedLog2LMULN2: 667*81ad6265SDimitry Andric applyFixedLog2LMUL(-2, FixedLMULType::LargerThan); 668*81ad6265SDimitry Andric break; 669*81ad6265SDimitry Andric case VectorTypeModifier::LFixedLog2LMULN1: 670*81ad6265SDimitry Andric applyFixedLog2LMUL(-1, FixedLMULType::LargerThan); 671*81ad6265SDimitry Andric break; 672*81ad6265SDimitry Andric case VectorTypeModifier::LFixedLog2LMUL0: 673*81ad6265SDimitry Andric applyFixedLog2LMUL(0, FixedLMULType::LargerThan); 674*81ad6265SDimitry Andric break; 675*81ad6265SDimitry Andric case VectorTypeModifier::LFixedLog2LMUL1: 676*81ad6265SDimitry Andric applyFixedLog2LMUL(1, FixedLMULType::LargerThan); 677*81ad6265SDimitry Andric break; 678*81ad6265SDimitry Andric case VectorTypeModifier::LFixedLog2LMUL2: 679*81ad6265SDimitry Andric applyFixedLog2LMUL(2, FixedLMULType::LargerThan); 680*81ad6265SDimitry Andric break; 681*81ad6265SDimitry Andric case VectorTypeModifier::LFixedLog2LMUL3: 682*81ad6265SDimitry Andric applyFixedLog2LMUL(3, FixedLMULType::LargerThan); 683*81ad6265SDimitry Andric break; 684*81ad6265SDimitry Andric case VectorTypeModifier::SFixedLog2LMULN3: 685*81ad6265SDimitry Andric applyFixedLog2LMUL(-3, FixedLMULType::SmallerThan); 686*81ad6265SDimitry Andric break; 687*81ad6265SDimitry Andric case VectorTypeModifier::SFixedLog2LMULN2: 688*81ad6265SDimitry Andric applyFixedLog2LMUL(-2, FixedLMULType::SmallerThan); 689*81ad6265SDimitry Andric break; 690*81ad6265SDimitry Andric case VectorTypeModifier::SFixedLog2LMULN1: 691*81ad6265SDimitry Andric applyFixedLog2LMUL(-1, FixedLMULType::SmallerThan); 692*81ad6265SDimitry Andric break; 693*81ad6265SDimitry Andric case VectorTypeModifier::SFixedLog2LMUL0: 694*81ad6265SDimitry Andric applyFixedLog2LMUL(0, FixedLMULType::SmallerThan); 695*81ad6265SDimitry Andric break; 696*81ad6265SDimitry Andric case VectorTypeModifier::SFixedLog2LMUL1: 697*81ad6265SDimitry Andric applyFixedLog2LMUL(1, FixedLMULType::SmallerThan); 698*81ad6265SDimitry Andric break; 699*81ad6265SDimitry Andric case VectorTypeModifier::SFixedLog2LMUL2: 700*81ad6265SDimitry Andric applyFixedLog2LMUL(2, FixedLMULType::SmallerThan); 701*81ad6265SDimitry Andric break; 702*81ad6265SDimitry Andric case VectorTypeModifier::SFixedLog2LMUL3: 703*81ad6265SDimitry Andric applyFixedLog2LMUL(3, FixedLMULType::SmallerThan); 704*81ad6265SDimitry Andric break; 705*81ad6265SDimitry Andric case VectorTypeModifier::NoModifier: 706*81ad6265SDimitry Andric break; 707*81ad6265SDimitry Andric } 708*81ad6265SDimitry Andric 709*81ad6265SDimitry Andric for (unsigned TypeModifierMaskShift = 0; 710*81ad6265SDimitry Andric TypeModifierMaskShift <= static_cast<unsigned>(TypeModifier::MaxOffset); 711*81ad6265SDimitry Andric ++TypeModifierMaskShift) { 712*81ad6265SDimitry Andric unsigned TypeModifierMask = 1 << TypeModifierMaskShift; 713*81ad6265SDimitry Andric if ((static_cast<unsigned>(Transformer.TM) & TypeModifierMask) != 714*81ad6265SDimitry Andric TypeModifierMask) 715*81ad6265SDimitry Andric continue; 716*81ad6265SDimitry Andric switch (static_cast<TypeModifier>(TypeModifierMask)) { 717*81ad6265SDimitry Andric case TypeModifier::Pointer: 718*81ad6265SDimitry Andric IsPointer = true; 719*81ad6265SDimitry Andric break; 720*81ad6265SDimitry Andric case TypeModifier::Const: 721*81ad6265SDimitry Andric IsConstant = true; 722*81ad6265SDimitry Andric break; 723*81ad6265SDimitry Andric case TypeModifier::Immediate: 724*81ad6265SDimitry Andric IsImmediate = true; 725*81ad6265SDimitry Andric IsConstant = true; 726*81ad6265SDimitry Andric break; 727*81ad6265SDimitry Andric case TypeModifier::UnsignedInteger: 728*81ad6265SDimitry Andric ScalarType = ScalarTypeKind::UnsignedInteger; 729*81ad6265SDimitry Andric break; 730*81ad6265SDimitry Andric case TypeModifier::SignedInteger: 731*81ad6265SDimitry Andric ScalarType = ScalarTypeKind::SignedInteger; 732*81ad6265SDimitry Andric break; 733*81ad6265SDimitry Andric case TypeModifier::Float: 734*81ad6265SDimitry Andric ScalarType = ScalarTypeKind::Float; 735*81ad6265SDimitry Andric break; 736*81ad6265SDimitry Andric case TypeModifier::LMUL1: 737*81ad6265SDimitry Andric LMUL = LMULType(0); 738*81ad6265SDimitry Andric // Update ElementBitwidth need to update Scale too. 739*81ad6265SDimitry Andric Scale = LMUL.getScale(ElementBitwidth); 740*81ad6265SDimitry Andric break; 741*81ad6265SDimitry Andric default: 742*81ad6265SDimitry Andric llvm_unreachable("Unknown type modifier mask!"); 743*81ad6265SDimitry Andric } 744*81ad6265SDimitry Andric } 745*81ad6265SDimitry Andric } 746*81ad6265SDimitry Andric 747*81ad6265SDimitry Andric void RVVType::applyLog2EEW(unsigned Log2EEW) { 748*81ad6265SDimitry Andric // update new elmul = (eew/sew) * lmul 749*81ad6265SDimitry Andric LMUL.MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth)); 750*81ad6265SDimitry Andric // update new eew 751*81ad6265SDimitry Andric ElementBitwidth = 1 << Log2EEW; 752*81ad6265SDimitry Andric ScalarType = ScalarTypeKind::SignedInteger; 753*81ad6265SDimitry Andric Scale = LMUL.getScale(ElementBitwidth); 754*81ad6265SDimitry Andric } 755*81ad6265SDimitry Andric 756*81ad6265SDimitry Andric void RVVType::applyFixedSEW(unsigned NewSEW) { 757*81ad6265SDimitry Andric // Set invalid type if src and dst SEW are same. 758*81ad6265SDimitry Andric if (ElementBitwidth == NewSEW) { 759*81ad6265SDimitry Andric ScalarType = ScalarTypeKind::Invalid; 760*81ad6265SDimitry Andric return; 761*81ad6265SDimitry Andric } 762*81ad6265SDimitry Andric // Update new SEW 763*81ad6265SDimitry Andric ElementBitwidth = NewSEW; 764*81ad6265SDimitry Andric Scale = LMUL.getScale(ElementBitwidth); 765*81ad6265SDimitry Andric } 766*81ad6265SDimitry Andric 767*81ad6265SDimitry Andric void RVVType::applyFixedLog2LMUL(int Log2LMUL, enum FixedLMULType Type) { 768*81ad6265SDimitry Andric switch (Type) { 769*81ad6265SDimitry Andric case FixedLMULType::LargerThan: 770*81ad6265SDimitry Andric if (Log2LMUL < LMUL.Log2LMUL) { 771*81ad6265SDimitry Andric ScalarType = ScalarTypeKind::Invalid; 772*81ad6265SDimitry Andric return; 773*81ad6265SDimitry Andric } 774*81ad6265SDimitry Andric break; 775*81ad6265SDimitry Andric case FixedLMULType::SmallerThan: 776*81ad6265SDimitry Andric if (Log2LMUL > LMUL.Log2LMUL) { 777*81ad6265SDimitry Andric ScalarType = ScalarTypeKind::Invalid; 778*81ad6265SDimitry Andric return; 779*81ad6265SDimitry Andric } 780*81ad6265SDimitry Andric break; 781*81ad6265SDimitry Andric } 782*81ad6265SDimitry Andric 783*81ad6265SDimitry Andric // Update new LMUL 784*81ad6265SDimitry Andric LMUL = LMULType(Log2LMUL); 785*81ad6265SDimitry Andric Scale = LMUL.getScale(ElementBitwidth); 786*81ad6265SDimitry Andric } 787*81ad6265SDimitry Andric 788*81ad6265SDimitry Andric Optional<RVVTypes> 789*81ad6265SDimitry Andric RVVType::computeTypes(BasicType BT, int Log2LMUL, unsigned NF, 790*81ad6265SDimitry Andric ArrayRef<PrototypeDescriptor> Prototype) { 791*81ad6265SDimitry Andric // LMUL x NF must be less than or equal to 8. 792*81ad6265SDimitry Andric if ((Log2LMUL >= 1) && (1 << Log2LMUL) * NF > 8) 793*81ad6265SDimitry Andric return llvm::None; 794*81ad6265SDimitry Andric 795*81ad6265SDimitry Andric RVVTypes Types; 796*81ad6265SDimitry Andric for (const PrototypeDescriptor &Proto : Prototype) { 797*81ad6265SDimitry Andric auto T = computeType(BT, Log2LMUL, Proto); 798*81ad6265SDimitry Andric if (!T) 799*81ad6265SDimitry Andric return llvm::None; 800*81ad6265SDimitry Andric // Record legal type index 801*81ad6265SDimitry Andric Types.push_back(T.getValue()); 802*81ad6265SDimitry Andric } 803*81ad6265SDimitry Andric return Types; 804*81ad6265SDimitry Andric } 805*81ad6265SDimitry Andric 806*81ad6265SDimitry Andric // Compute the hash value of RVVType, used for cache the result of computeType. 807*81ad6265SDimitry Andric static uint64_t computeRVVTypeHashValue(BasicType BT, int Log2LMUL, 808*81ad6265SDimitry Andric PrototypeDescriptor Proto) { 809*81ad6265SDimitry Andric // Layout of hash value: 810*81ad6265SDimitry Andric // 0 8 16 24 32 40 811*81ad6265SDimitry Andric // | Log2LMUL + 3 | BT | Proto.PT | Proto.TM | Proto.VTM | 812*81ad6265SDimitry Andric assert(Log2LMUL >= -3 && Log2LMUL <= 3); 813*81ad6265SDimitry Andric return (Log2LMUL + 3) | (static_cast<uint64_t>(BT) & 0xff) << 8 | 814*81ad6265SDimitry Andric ((uint64_t)(Proto.PT & 0xff) << 16) | 815*81ad6265SDimitry Andric ((uint64_t)(Proto.TM & 0xff) << 24) | 816*81ad6265SDimitry Andric ((uint64_t)(Proto.VTM & 0xff) << 32); 817*81ad6265SDimitry Andric } 818*81ad6265SDimitry Andric 819*81ad6265SDimitry Andric Optional<RVVTypePtr> RVVType::computeType(BasicType BT, int Log2LMUL, 820*81ad6265SDimitry Andric PrototypeDescriptor Proto) { 821*81ad6265SDimitry Andric // Concat BasicType, LMUL and Proto as key 822*81ad6265SDimitry Andric static std::unordered_map<uint64_t, RVVType> LegalTypes; 823*81ad6265SDimitry Andric static std::set<uint64_t> IllegalTypes; 824*81ad6265SDimitry Andric uint64_t Idx = computeRVVTypeHashValue(BT, Log2LMUL, Proto); 825*81ad6265SDimitry Andric // Search first 826*81ad6265SDimitry Andric auto It = LegalTypes.find(Idx); 827*81ad6265SDimitry Andric if (It != LegalTypes.end()) 828*81ad6265SDimitry Andric return &(It->second); 829*81ad6265SDimitry Andric 830*81ad6265SDimitry Andric if (IllegalTypes.count(Idx)) 831*81ad6265SDimitry Andric return llvm::None; 832*81ad6265SDimitry Andric 833*81ad6265SDimitry Andric // Compute type and record the result. 834*81ad6265SDimitry Andric RVVType T(BT, Log2LMUL, Proto); 835*81ad6265SDimitry Andric if (T.isValid()) { 836*81ad6265SDimitry Andric // Record legal type index and value. 837*81ad6265SDimitry Andric LegalTypes.insert({Idx, T}); 838*81ad6265SDimitry Andric return &(LegalTypes[Idx]); 839*81ad6265SDimitry Andric } 840*81ad6265SDimitry Andric // Record illegal type index. 841*81ad6265SDimitry Andric IllegalTypes.insert(Idx); 842*81ad6265SDimitry Andric return llvm::None; 843*81ad6265SDimitry Andric } 844*81ad6265SDimitry Andric 845*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 846*81ad6265SDimitry Andric // RVVIntrinsic implementation 847*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 848*81ad6265SDimitry Andric RVVIntrinsic::RVVIntrinsic( 849*81ad6265SDimitry Andric StringRef NewName, StringRef Suffix, StringRef NewOverloadedName, 850*81ad6265SDimitry Andric StringRef OverloadedSuffix, StringRef IRName, bool IsMasked, 851*81ad6265SDimitry Andric bool HasMaskedOffOperand, bool HasVL, PolicyScheme Scheme, 852*81ad6265SDimitry Andric bool HasUnMaskedOverloaded, bool HasBuiltinAlias, StringRef ManualCodegen, 853*81ad6265SDimitry Andric const RVVTypes &OutInTypes, const std::vector<int64_t> &NewIntrinsicTypes, 854*81ad6265SDimitry Andric const std::vector<StringRef> &RequiredFeatures, unsigned NF) 855*81ad6265SDimitry Andric : IRName(IRName), IsMasked(IsMasked), HasVL(HasVL), Scheme(Scheme), 856*81ad6265SDimitry Andric HasUnMaskedOverloaded(HasUnMaskedOverloaded), 857*81ad6265SDimitry Andric HasBuiltinAlias(HasBuiltinAlias), ManualCodegen(ManualCodegen.str()), 858*81ad6265SDimitry Andric NF(NF) { 859*81ad6265SDimitry Andric 860*81ad6265SDimitry Andric // Init BuiltinName, Name and OverloadedName 861*81ad6265SDimitry Andric BuiltinName = NewName.str(); 862*81ad6265SDimitry Andric Name = BuiltinName; 863*81ad6265SDimitry Andric if (NewOverloadedName.empty()) 864*81ad6265SDimitry Andric OverloadedName = NewName.split("_").first.str(); 865*81ad6265SDimitry Andric else 866*81ad6265SDimitry Andric OverloadedName = NewOverloadedName.str(); 867*81ad6265SDimitry Andric if (!Suffix.empty()) 868*81ad6265SDimitry Andric Name += "_" + Suffix.str(); 869*81ad6265SDimitry Andric if (!OverloadedSuffix.empty()) 870*81ad6265SDimitry Andric OverloadedName += "_" + OverloadedSuffix.str(); 871*81ad6265SDimitry Andric if (IsMasked) { 872*81ad6265SDimitry Andric BuiltinName += "_m"; 873*81ad6265SDimitry Andric Name += "_m"; 874*81ad6265SDimitry Andric } 875*81ad6265SDimitry Andric 876*81ad6265SDimitry Andric // Init RISC-V extensions 877*81ad6265SDimitry Andric for (const auto &T : OutInTypes) { 878*81ad6265SDimitry Andric if (T->isFloatVector(16) || T->isFloat(16)) 879*81ad6265SDimitry Andric RISCVPredefinedMacros |= RISCVPredefinedMacro::Zvfh; 880*81ad6265SDimitry Andric if (T->isFloatVector(32)) 881*81ad6265SDimitry Andric RISCVPredefinedMacros |= RISCVPredefinedMacro::VectorMaxELenFp32; 882*81ad6265SDimitry Andric if (T->isFloatVector(64)) 883*81ad6265SDimitry Andric RISCVPredefinedMacros |= RISCVPredefinedMacro::VectorMaxELenFp64; 884*81ad6265SDimitry Andric if (T->isVector(64)) 885*81ad6265SDimitry Andric RISCVPredefinedMacros |= RISCVPredefinedMacro::VectorMaxELen64; 886*81ad6265SDimitry Andric } 887*81ad6265SDimitry Andric for (auto Feature : RequiredFeatures) { 888*81ad6265SDimitry Andric if (Feature == "RV64") 889*81ad6265SDimitry Andric RISCVPredefinedMacros |= RISCVPredefinedMacro::RV64; 890*81ad6265SDimitry Andric // Note: Full multiply instruction (mulh, mulhu, mulhsu, smul) for EEW=64 891*81ad6265SDimitry Andric // require V. 892*81ad6265SDimitry Andric if (Feature == "FullMultiply" && 893*81ad6265SDimitry Andric (RISCVPredefinedMacros & RISCVPredefinedMacro::VectorMaxELen64)) 894*81ad6265SDimitry Andric RISCVPredefinedMacros |= RISCVPredefinedMacro::V; 895*81ad6265SDimitry Andric } 896*81ad6265SDimitry Andric 897*81ad6265SDimitry Andric // Init OutputType and InputTypes 898*81ad6265SDimitry Andric OutputType = OutInTypes[0]; 899*81ad6265SDimitry Andric InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end()); 900*81ad6265SDimitry Andric 901*81ad6265SDimitry Andric // IntrinsicTypes is unmasked TA version index. Need to update it 902*81ad6265SDimitry Andric // if there is merge operand (It is always in first operand). 903*81ad6265SDimitry Andric IntrinsicTypes = NewIntrinsicTypes; 904*81ad6265SDimitry Andric if ((IsMasked && HasMaskedOffOperand) || 905*81ad6265SDimitry Andric (!IsMasked && hasPassthruOperand())) { 906*81ad6265SDimitry Andric for (auto &I : IntrinsicTypes) { 907*81ad6265SDimitry Andric if (I >= 0) 908*81ad6265SDimitry Andric I += NF; 909*81ad6265SDimitry Andric } 910*81ad6265SDimitry Andric } 911*81ad6265SDimitry Andric } 912*81ad6265SDimitry Andric 913*81ad6265SDimitry Andric std::string RVVIntrinsic::getBuiltinTypeStr() const { 914*81ad6265SDimitry Andric std::string S; 915*81ad6265SDimitry Andric S += OutputType->getBuiltinStr(); 916*81ad6265SDimitry Andric for (const auto &T : InputTypes) { 917*81ad6265SDimitry Andric S += T->getBuiltinStr(); 918*81ad6265SDimitry Andric } 919*81ad6265SDimitry Andric return S; 920*81ad6265SDimitry Andric } 921*81ad6265SDimitry Andric 922*81ad6265SDimitry Andric std::string RVVIntrinsic::getSuffixStr( 923*81ad6265SDimitry Andric BasicType Type, int Log2LMUL, 924*81ad6265SDimitry Andric llvm::ArrayRef<PrototypeDescriptor> PrototypeDescriptors) { 925*81ad6265SDimitry Andric SmallVector<std::string> SuffixStrs; 926*81ad6265SDimitry Andric for (auto PD : PrototypeDescriptors) { 927*81ad6265SDimitry Andric auto T = RVVType::computeType(Type, Log2LMUL, PD); 928*81ad6265SDimitry Andric SuffixStrs.push_back((*T)->getShortStr()); 929*81ad6265SDimitry Andric } 930*81ad6265SDimitry Andric return join(SuffixStrs, "_"); 931*81ad6265SDimitry Andric } 932*81ad6265SDimitry Andric 933*81ad6265SDimitry Andric SmallVector<PrototypeDescriptor> parsePrototypes(StringRef Prototypes) { 934*81ad6265SDimitry Andric SmallVector<PrototypeDescriptor> PrototypeDescriptors; 935*81ad6265SDimitry Andric const StringRef Primaries("evwqom0ztul"); 936*81ad6265SDimitry Andric while (!Prototypes.empty()) { 937*81ad6265SDimitry Andric size_t Idx = 0; 938*81ad6265SDimitry Andric // Skip over complex prototype because it could contain primitive type 939*81ad6265SDimitry Andric // character. 940*81ad6265SDimitry Andric if (Prototypes[0] == '(') 941*81ad6265SDimitry Andric Idx = Prototypes.find_first_of(')'); 942*81ad6265SDimitry Andric Idx = Prototypes.find_first_of(Primaries, Idx); 943*81ad6265SDimitry Andric assert(Idx != StringRef::npos); 944*81ad6265SDimitry Andric auto PD = PrototypeDescriptor::parsePrototypeDescriptor( 945*81ad6265SDimitry Andric Prototypes.slice(0, Idx + 1)); 946*81ad6265SDimitry Andric if (!PD) 947*81ad6265SDimitry Andric llvm_unreachable("Error during parsing prototype."); 948*81ad6265SDimitry Andric PrototypeDescriptors.push_back(*PD); 949*81ad6265SDimitry Andric Prototypes = Prototypes.drop_front(Idx + 1); 950*81ad6265SDimitry Andric } 951*81ad6265SDimitry Andric return PrototypeDescriptors; 952*81ad6265SDimitry Andric } 953*81ad6265SDimitry Andric 954*81ad6265SDimitry Andric } // end namespace RISCV 955*81ad6265SDimitry Andric } // end namespace clang 956