10#include "llvm/ADT/ArrayRef.h"
11#include "llvm/ADT/SmallSet.h"
12#include "llvm/ADT/StringExtras.h"
13#include "llvm/ADT/StringMap.h"
14#include "llvm/ADT/StringSet.h"
15#include "llvm/ADT/Twine.h"
16#include "llvm/Support/ErrorHandling.h"
17#include "llvm/Support/raw_ostream.h"
39 assert(NewLog2LMUL <= 3 && NewLog2LMUL >= -3 &&
"Bad LMUL number!");
45 return "mf" + utostr(1ULL << (-
Log2LMUL));
46 return "m" + utostr(1ULL <<
Log2LMUL);
50 int Log2ScaleResult = 0;
51 switch (ElementBitwidth) {
68 if (Log2ScaleResult < 0)
70 return 1 << Log2ScaleResult;
75RVVType::RVVType(
BasicType BT,
int Log2LMUL,
79 applyModifier(prototype);
85 initClangBuiltinStr();
107bool RVVType::verifyType()
const {
114 if (
isFloat() && ElementBitwidth == 8)
117 switch (ElementBitwidth) {
121 return (
V <= 64 && isPowerOf2_32(
V));
124 return (
V <= 32 && isPowerOf2_32(
V));
127 return (
V <= 16 && isPowerOf2_32(
V));
130 return (
V <= 8 && isPowerOf2_32(
V));
135void RVVType::initBuiltinStr() {
136 assert(
isValid() &&
"RVVType is invalid");
137 switch (ScalarType) {
144 BuiltinStr =
"I" + BuiltinStr;
158 assert(ElementBitwidth == 1);
163 switch (ElementBitwidth) {
177 llvm_unreachable(
"Unhandled ElementBitwidth!");
180 BuiltinStr =
"S" + BuiltinStr;
182 BuiltinStr =
"U" + BuiltinStr;
185 switch (ElementBitwidth) {
196 llvm_unreachable(
"Unhandled ElementBitwidth!");
200 llvm_unreachable(
"ScalarType is invalid!");
203 BuiltinStr =
"I" + BuiltinStr;
211 BuiltinStr =
"q" + utostr(*Scale) + BuiltinStr;
219void RVVType::initClangBuiltinStr() {
220 assert(
isValid() &&
"RVVType is invalid");
221 assert(
isVector() &&
"Handle Vector type only");
223 ClangBuiltinStr =
"__rvv_";
224 switch (ScalarType) {
226 ClangBuiltinStr +=
"bool" + utostr(64 / *Scale) +
"_t";
229 ClangBuiltinStr +=
"float";
232 ClangBuiltinStr +=
"int";
235 ClangBuiltinStr +=
"uint";
238 llvm_unreachable(
"ScalarTypeKind is invalid");
240 ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.
str() +
"_t";
243void RVVType::initTypeStr() {
244 assert(
isValid() &&
"RVVType is invalid");
251 return Twine(TypeStr + Twine(ElementBitwidth) +
"_t").str();
252 return Twine(
"v" + TypeStr + Twine(ElementBitwidth) + LMUL.
str() +
"_t")
256 switch (ScalarType) {
269 Str =
"unsigned long";
280 Str +=
"vbool" + utostr(64 / *Scale) +
"_t";
284 if (ElementBitwidth == 64)
286 else if (ElementBitwidth == 32)
288 else if (ElementBitwidth == 16)
291 llvm_unreachable(
"Unhandled floating type.");
302 llvm_unreachable(
"ScalarType is invalid!");
308void RVVType::initShortStr() {
309 switch (ScalarType) {
312 ShortStr =
"b" + utostr(64 / *Scale);
315 ShortStr =
"f" + utostr(ElementBitwidth);
318 ShortStr =
"i" + utostr(ElementBitwidth);
321 ShortStr =
"u" + utostr(ElementBitwidth);
324 llvm_unreachable(
"Unhandled case!");
327 ShortStr += LMUL.
str();
330void RVVType::applyBasicType() {
337 ElementBitwidth = 16;
341 ElementBitwidth = 32;
345 ElementBitwidth = 64;
349 ElementBitwidth = 16;
353 ElementBitwidth = 32;
357 ElementBitwidth = 64;
361 llvm_unreachable(
"Unhandled type code!");
363 assert(ElementBitwidth != 0 &&
"Bad element bitwidth!");
366std::optional<PrototypeDescriptor>
368 llvm::StringRef PrototypeDescriptorStr) {
373 if (PrototypeDescriptorStr.empty())
377 auto PType = PrototypeDescriptorStr.back();
417 llvm_unreachable(
"Illegal primitive type transformers!");
419 PD.
PT =
static_cast<uint8_t
>(
PT);
420 PrototypeDescriptorStr = PrototypeDescriptorStr.drop_back();
423 if (PrototypeDescriptorStr.startswith(
"(")) {
425 "VectorTypeModifier should only have one modifier");
426 size_t Idx = PrototypeDescriptorStr.find(
')');
427 assert(Idx != StringRef::npos);
428 StringRef
ComplexType = PrototypeDescriptorStr.slice(1, Idx);
429 PrototypeDescriptorStr = PrototypeDescriptorStr.drop_front(Idx + 1);
430 assert(!PrototypeDescriptorStr.contains(
'(') &&
431 "Only allow one vector type modifier");
434 if (ComplexTT.first ==
"Log2EEW") {
436 if (ComplexTT.second.getAsInteger(10, Log2EEW)) {
437 llvm_unreachable(
"Invalid Log2EEW value!");
454 llvm_unreachable(
"Invalid Log2EEW value, should be [3-6]");
457 }
else if (ComplexTT.first ==
"FixedSEW") {
459 if (ComplexTT.second.getAsInteger(10, NewSEW)) {
460 llvm_unreachable(
"Invalid FixedSEW value!");
477 llvm_unreachable(
"Invalid FixedSEW value, should be 8, 16, 32 or 64");
480 }
else if (ComplexTT.first ==
"LFixedLog2LMUL") {
482 if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
483 llvm_unreachable(
"Invalid LFixedLog2LMUL value!");
509 llvm_unreachable(
"Invalid LFixedLog2LMUL value, should be [-3, 3]");
512 }
else if (ComplexTT.first ==
"SFixedLog2LMUL") {
514 if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
515 llvm_unreachable(
"Invalid SFixedLog2LMUL value!");
541 llvm_unreachable(
"Invalid LFixedLog2LMUL value, should be [-3, 3]");
546 llvm_unreachable(
"Illegal complex type transformers!");
549 PD.
VTM =
static_cast<uint8_t
>(
VTM);
553 for (
char I : PrototypeDescriptorStr) {
557 llvm_unreachable(
"'P' transformer cannot be used after 'C'");
559 llvm_unreachable(
"'P' transformer cannot be used twice");
581 llvm_unreachable(
"Illegal non-primitive type transformer!");
584 PD.
TM =
static_cast<uint8_t
>(
TM);
596 Scale = LMUL.
getScale(ElementBitwidth);
620 ElementBitwidth *= 2;
622 Scale = LMUL.
getScale(ElementBitwidth);
625 ElementBitwidth *= 4;
627 Scale = LMUL.
getScale(ElementBitwidth);
630 ElementBitwidth *= 8;
632 Scale = LMUL.
getScale(ElementBitwidth);
636 Scale = LMUL.
getScale(ElementBitwidth);
664 applyFixedLog2LMUL(-3, FixedLMULType::LargerThan);
667 applyFixedLog2LMUL(-2, FixedLMULType::LargerThan);
670 applyFixedLog2LMUL(-1, FixedLMULType::LargerThan);
673 applyFixedLog2LMUL(0, FixedLMULType::LargerThan);
676 applyFixedLog2LMUL(1, FixedLMULType::LargerThan);
679 applyFixedLog2LMUL(2, FixedLMULType::LargerThan);
682 applyFixedLog2LMUL(3, FixedLMULType::LargerThan);
685 applyFixedLog2LMUL(-3, FixedLMULType::SmallerThan);
688 applyFixedLog2LMUL(-2, FixedLMULType::SmallerThan);
691 applyFixedLog2LMUL(-1, FixedLMULType::SmallerThan);
694 applyFixedLog2LMUL(0, FixedLMULType::SmallerThan);
697 applyFixedLog2LMUL(1, FixedLMULType::SmallerThan);
700 applyFixedLog2LMUL(2, FixedLMULType::SmallerThan);
703 applyFixedLog2LMUL(3, FixedLMULType::SmallerThan);
709 for (
unsigned TypeModifierMaskShift = 0;
711 ++TypeModifierMaskShift) {
712 unsigned TypeModifierMask = 1 << TypeModifierMaskShift;
713 if ((
static_cast<unsigned>(Transformer.
TM) & TypeModifierMask) !=
739 Scale = LMUL.
getScale(ElementBitwidth);
742 llvm_unreachable(
"Unknown type modifier mask!");
747void RVVType::applyLog2EEW(
unsigned Log2EEW) {
749 LMUL.
MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth));
751 ElementBitwidth = 1 << Log2EEW;
753 Scale = LMUL.
getScale(ElementBitwidth);
756void RVVType::applyFixedSEW(
unsigned NewSEW) {
758 if (ElementBitwidth == NewSEW) {
763 ElementBitwidth = NewSEW;
764 Scale = LMUL.
getScale(ElementBitwidth);
767void RVVType::applyFixedLog2LMUL(
int Log2LMUL,
enum FixedLMULType Type) {
769 case FixedLMULType::LargerThan:
775 case FixedLMULType::SmallerThan:
784 LMUL = LMULType(Log2LMUL);
785 Scale = LMUL.
getScale(ElementBitwidth);
788std::optional<RVVTypes>
792 if ((Log2LMUL >= 1) && (1 << Log2LMUL) * NF > 8)
812 assert(Log2LMUL >= -3 && Log2LMUL <= 3);
813 return (Log2LMUL + 3) | (
static_cast<uint64_t
>(BT) & 0xff) << 8 |
814 ((uint64_t)(Proto.
PT & 0xff) << 16) |
815 ((uint64_t)(Proto.
TM & 0xff) << 24) |
816 ((uint64_t)(Proto.
VTM & 0xff) << 32);
823 auto It = LegalTypes.find(Idx);
824 if (It != LegalTypes.end())
825 return &(It->second);
827 if (IllegalTypes.count(Idx))
831 RVVType T(BT, Log2LMUL, Proto);
834 std::pair<std::unordered_map<uint64_t, RVVType>::iterator,
bool>
835 InsertResult = LegalTypes.insert({Idx, T});
836 return &(InsertResult.first->second);
839 IllegalTypes.insert(Idx);
847 StringRef NewOverloadedName,
848 StringRef OverloadedSuffix, StringRef IRName,
849 bool IsMasked,
bool HasMaskedOffOperand,
bool HasVL,
851 bool HasBuiltinAlias, StringRef ManualCodegen,
853 const std::vector<int64_t> &NewIntrinsicTypes,
854 const std::vector<StringRef> &RequiredFeatures,
855 unsigned NF,
Policy NewPolicyAttrs)
856 : IRName(IRName), IsMasked(IsMasked),
857 HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme),
858 SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias),
859 ManualCodegen(ManualCodegen.str()), NF(NF), PolicyAttrs(NewPolicyAttrs) {
862 BuiltinName = NewName.str();
864 if (NewOverloadedName.empty())
865 OverloadedName = NewName.split(
"_").first.str();
867 OverloadedName = NewOverloadedName.str();
869 Name +=
"_" + Suffix.str();
870 if (!OverloadedSuffix.empty())
871 OverloadedName +=
"_" + OverloadedSuffix.str();
877 OutputType = OutInTypes[0];
878 InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
882 IntrinsicTypes = NewIntrinsicTypes;
885 for (
auto &I : IntrinsicTypes) {
895 for (
const auto &T : InputTypes) {
896 S += T->getBuiltinStr();
905 for (
auto PD : PrototypeDescriptors) {
907 SuffixStrs.push_back((*T)->getShortStr());
909 return join(SuffixStrs,
"_");
914 bool HasMaskedOffOperand,
bool HasVL,
unsigned NF,
922 if (HasMaskedOffOperand && !PolicyAttrs.
isTAMAPolicy()) {
924 NewPrototype.insert(NewPrototype.begin() + 1, NewPrototype[0]);
932 NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
935 if (HasMaskedOffOperand && NF > 1) {
941 NewPrototype.insert(NewPrototype.begin() + NF + 1,
949 if (PolicyAttrs.
isTUPolicy() && HasPassthruOp)
950 NewPrototype.insert(NewPrototype.begin(), NewPrototype[0]);
951 }
else if (PolicyAttrs.
isTUPolicy() && HasPassthruOp) {
959 NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
975 bool HasMaskPolicy) {
976 if (HasTailPolicy && HasMaskPolicy)
983 if (HasTailPolicy && !HasMaskPolicy)
986 if (!HasTailPolicy && HasMaskPolicy)
989 llvm_unreachable(
"An RVV instruction should not be without both tail policy "
995 std::string &BuiltinName,
996 std::string &OverloadedName,
999 auto appendPolicySuffix = [&](
const std::string &suffix) {
1001 BuiltinName += suffix;
1002 OverloadedName += suffix;
1007 Name =
"__riscv_" + Name;
1008 OverloadedName =
"__riscv_" + OverloadedName;
1012 appendPolicySuffix(
"_tumu");
1014 appendPolicySuffix(
"_tum");
1016 appendPolicySuffix(
"_mu");
1020 BuiltinName +=
"_tama";
1022 BuiltinName +=
"_m";
1024 llvm_unreachable(
"Unhandled policy condition");
1027 appendPolicySuffix(
"_tu");
1030 BuiltinName +=
"_ta";
1032 llvm_unreachable(
"Unhandled policy condition");
1038 const StringRef Primaries(
"evwqom0ztul");
1039 while (!Prototypes.empty()) {
1043 if (Prototypes[0] ==
'(')
1044 Idx = Prototypes.find_first_of(
')');
1045 Idx = Prototypes.find_first_of(Primaries, Idx);
1046 assert(Idx != StringRef::npos);
1048 Prototypes.slice(0, Idx + 1));
1050 llvm_unreachable(
"Error during parsing prototype.");
1051 PrototypeDescriptors.push_back(*PD);
1052 Prototypes = Prototypes.drop_front(Idx + 1);
1054 return PrototypeDescriptors;
1059 OS <<
"\"" << Record.Name <<
"\",";
1060 if (Record.OverloadedName ==
nullptr ||
1061 StringRef(Record.OverloadedName).empty())
1064 OS <<
"\"" << Record.OverloadedName <<
"\",";
1065 OS << Record.PrototypeIndex <<
",";
1066 OS << Record.SuffixIndex <<
",";
1067 OS << Record.OverloadedSuffixIndex <<
",";
1068 OS << (
int)Record.PrototypeLength <<
",";
1069 OS << (
int)Record.SuffixLength <<
",";
1070 OS << (
int)Record.OverloadedSuffixSize <<
",";
1071 OS << (
int)Record.RequiredExtensions <<
",";
1072 OS << (
int)Record.TypeRangeMask <<
",";
1073 OS << (
int)Record.Log2LMULMask <<
",";
1074 OS << (
int)Record.NF <<
",";
1075 OS << (
int)Record.HasMasked <<
",";
1076 OS << (
int)Record.HasVL <<
",";
1077 OS << (
int)Record.HasMaskedOffOperand <<
",";
1078 OS << (
int)Record.HasTailPolicy <<
",";
1079 OS << (
int)Record.HasMaskPolicy <<
",";
1080 OS << (
int)Record.UnMaskedPolicyScheme <<
",";
1081 OS << (
int)Record.MaskedPolicyScheme <<
",";
static bool getTypeString(SmallStringEnc &Enc, const Decl *D, const CodeGen::CodeGenModule &CGM, TypeStringCache &TSC)
The XCore ABI includes a type information section that communicates symbol type information to the li...
static bool isVector(QualType QT, QualType ElementType)
This helper function returns true if QT is a vector type that has element type ElementType.
Complex values, per C99 6.2.5p11.
bool isTUMUPolicy() const
bool isTUMAPolicy() const
bool isTAMUPolicy() const
bool isTAMAPolicy() const
RVVIntrinsic(llvm::StringRef Name, llvm::StringRef Suffix, llvm::StringRef OverloadedName, llvm::StringRef OverloadedSuffix, llvm::StringRef IRName, bool IsMasked, bool HasMaskedOffOperand, bool HasVL, PolicyScheme Scheme, bool SupportOverloading, bool HasBuiltinAlias, llvm::StringRef ManualCodegen, const RVVTypes &Types, const std::vector< int64_t > &IntrinsicTypes, const std::vector< llvm::StringRef > &RequiredFeatures, unsigned NF, Policy PolicyAttrs)
bool hasPassthruOperand() const
static llvm::SmallVector< Policy > getSupportedMaskedPolicies(bool HasTailPolicy, bool HasMaskPolicy)
bool hasMaskedOffOperand() const
static std::string getSuffixStr(RVVTypeCache &TypeCache, BasicType Type, int Log2LMUL, llvm::ArrayRef< PrototypeDescriptor > PrototypeDescriptors)
static void updateNamesAndPolicy(bool IsMasked, bool HasPolicy, std::string &Name, std::string &BuiltinName, std::string &OverloadedName, Policy &PolicyAttrs)
static llvm::SmallVector< PrototypeDescriptor > computeBuiltinTypes(llvm::ArrayRef< PrototypeDescriptor > Prototype, bool IsMasked, bool HasMaskedOffOperand, bool HasVL, unsigned NF, PolicyScheme DefaultScheme, Policy PolicyAttrs)
static llvm::SmallVector< Policy > getSupportedUnMaskedPolicies()
std::string getBuiltinTypeStr() const
std::optional< RVVTypePtr > computeType(BasicType BT, int Log2LMUL, PrototypeDescriptor Proto)
std::optional< RVVTypes > computeTypes(BasicType BT, int Log2LMUL, unsigned NF, llvm::ArrayRef< PrototypeDescriptor > Prototype)
Compute output and input types by applying different config (basic type and LMUL with type transforme...
bool isSignedInteger() const
const std::string & getBuiltinStr() const
The base class of the type hierarchy.
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const RVVIntrinsicRecord &RVVInstrRecord)
llvm::SmallVector< PrototypeDescriptor > parsePrototypes(llvm::StringRef Prototypes)
static uint64_t computeRVVTypeHashValue(BasicType BT, int Log2LMUL, PrototypeDescriptor Proto)
std::optional< unsigned > VScaleVal
std::vector< RVVTypePtr > RVVTypes
YAML serialization mapping.
std::optional< unsigned > getScale(unsigned ElementBitwidth) const
void MulLog2LMUL(int Log2LMUL)
static std::optional< PrototypeDescriptor > parsePrototypeDescriptor(llvm::StringRef PrototypeStr)
static const PrototypeDescriptor VL
static const PrototypeDescriptor Mask
static const PrototypeDescriptor Vector