10#include "llvm/ADT/ArrayRef.h"
11#include "llvm/ADT/SmallSet.h"
12#include "llvm/ADT/StringExtras.h"
13#include "llvm/ADT/StringSet.h"
14#include "llvm/ADT/Twine.h"
15#include "llvm/Support/ErrorHandling.h"
16#include "llvm/Support/raw_ostream.h"
38 assert(NewLog2LMUL <= 3 && NewLog2LMUL >= -3 &&
"Bad LMUL number!");
44 return "mf" + utostr(1ULL << (-
Log2LMUL));
45 return "m" + utostr(1ULL <<
Log2LMUL);
49 int Log2ScaleResult = 0;
50 switch (ElementBitwidth) {
67 if (Log2ScaleResult < 0)
69 return 1 << Log2ScaleResult;
74RVVType::RVVType(
BasicType BT,
int Log2LMUL,
78 applyModifier(prototype);
84 initClangBuiltinStr();
107bool RVVType::verifyType()
const {
114 if (
isFloat() && ElementBitwidth == 8)
116 if (
isBFloat() && ElementBitwidth != 16)
118 if (IsTuple && (NF == 1 || NF > 8))
120 if (IsTuple && (1 << std::max(0, LMUL.
Log2LMUL)) * NF > 8)
123 switch (ElementBitwidth) {
127 return (
V <= 64 && isPowerOf2_32(
V));
130 return (
V <= 32 && isPowerOf2_32(
V));
133 return (
V <= 16 && isPowerOf2_32(
V));
136 return (
V <= 8 && isPowerOf2_32(
V));
141void RVVType::initBuiltinStr() {
142 assert(
isValid() &&
"RVVType is invalid");
143 switch (ScalarType) {
150 BuiltinStr =
"I" + BuiltinStr;
164 assert(ElementBitwidth == 1);
169 switch (ElementBitwidth) {
183 llvm_unreachable(
"Unhandled ElementBitwidth!");
186 BuiltinStr =
"S" + BuiltinStr;
188 BuiltinStr =
"U" + BuiltinStr;
191 switch (ElementBitwidth) {
202 llvm_unreachable(
"Unhandled ElementBitwidth!");
209 llvm_unreachable(
"ScalarType is invalid!");
212 BuiltinStr =
"I" + BuiltinStr;
220 BuiltinStr =
"q" + utostr(*Scale) + BuiltinStr;
228 BuiltinStr =
"T" + utostr(NF) + BuiltinStr;
231void RVVType::initClangBuiltinStr() {
232 assert(
isValid() &&
"RVVType is invalid");
233 assert(
isVector() &&
"Handle Vector type only");
235 ClangBuiltinStr =
"__rvv_";
236 switch (ScalarType) {
238 ClangBuiltinStr +=
"bool" + utostr(64 / *Scale) +
"_t";
241 ClangBuiltinStr +=
"float";
244 ClangBuiltinStr +=
"bfloat";
247 ClangBuiltinStr +=
"int";
250 ClangBuiltinStr +=
"uint";
253 llvm_unreachable(
"ScalarTypeKind is invalid");
255 ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.
str() +
256 (IsTuple ?
"x" + utostr(NF) :
"") +
"_t";
259void RVVType::initTypeStr() {
260 assert(
isValid() &&
"RVVType is invalid");
267 return Twine(TypeStr + Twine(ElementBitwidth) +
"_t").str();
268 return Twine(
"v" + TypeStr + Twine(ElementBitwidth) + LMUL.
str() +
269 (IsTuple ?
"x" + utostr(NF) :
"") +
"_t")
273 switch (ScalarType) {
286 Str =
"unsigned long";
297 Str +=
"vbool" + utostr(64 / *Scale) +
"_t";
301 if (ElementBitwidth == 64)
303 else if (ElementBitwidth == 32)
305 else if (ElementBitwidth == 16)
308 llvm_unreachable(
"Unhandled floating type.");
314 if (ElementBitwidth == 16)
317 llvm_unreachable(
"Unhandled floating type.");
328 llvm_unreachable(
"ScalarType is invalid!");
334void RVVType::initShortStr() {
335 switch (ScalarType) {
338 ShortStr =
"b" + utostr(64 / *Scale);
341 ShortStr =
"f" + utostr(ElementBitwidth);
344 ShortStr =
"bf" + utostr(ElementBitwidth);
347 ShortStr =
"i" + utostr(ElementBitwidth);
350 ShortStr =
"u" + utostr(ElementBitwidth);
353 llvm_unreachable(
"Unhandled case!");
356 ShortStr += LMUL.
str();
358 ShortStr +=
"x" + utostr(NF);
362 assert(2 <= NF && NF <= 8 &&
"2 <= NF <= 8");
367void RVVType::applyBasicType() {
374 ElementBitwidth = 16;
378 ElementBitwidth = 32;
382 ElementBitwidth = 64;
386 ElementBitwidth = 16;
390 ElementBitwidth = 32;
394 ElementBitwidth = 64;
398 ElementBitwidth = 16;
402 llvm_unreachable(
"Unhandled type code!");
404 assert(ElementBitwidth != 0 &&
"Bad element bitwidth!");
407std::optional<PrototypeDescriptor>
409 llvm::StringRef PrototypeDescriptorStr) {
414 if (PrototypeDescriptorStr.empty())
418 auto PType = PrototypeDescriptorStr.back();
461 llvm_unreachable(
"Illegal primitive type transformers!");
463 PD.
PT =
static_cast<uint8_t
>(
PT);
464 PrototypeDescriptorStr = PrototypeDescriptorStr.drop_back();
467 if (PrototypeDescriptorStr.starts_with(
"(")) {
469 "VectorTypeModifier should only have one modifier");
470 size_t Idx = PrototypeDescriptorStr.find(
')');
471 assert(Idx != StringRef::npos);
472 StringRef
ComplexType = PrototypeDescriptorStr.slice(1, Idx);
473 PrototypeDescriptorStr = PrototypeDescriptorStr.drop_front(Idx + 1);
474 assert(!PrototypeDescriptorStr.contains(
'(') &&
475 "Only allow one vector type modifier");
478 if (ComplexTT.first ==
"Log2EEW") {
480 if (ComplexTT.second.getAsInteger(10, Log2EEW)) {
481 llvm_unreachable(
"Invalid Log2EEW value!");
498 llvm_unreachable(
"Invalid Log2EEW value, should be [3-6]");
501 }
else if (ComplexTT.first ==
"FixedSEW") {
503 if (ComplexTT.second.getAsInteger(10, NewSEW)) {
504 llvm_unreachable(
"Invalid FixedSEW value!");
521 llvm_unreachable(
"Invalid FixedSEW value, should be 8, 16, 32 or 64");
524 }
else if (ComplexTT.first ==
"LFixedLog2LMUL") {
526 if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
527 llvm_unreachable(
"Invalid LFixedLog2LMUL value!");
553 llvm_unreachable(
"Invalid LFixedLog2LMUL value, should be [-3, 3]");
556 }
else if (ComplexTT.first ==
"SFixedLog2LMUL") {
558 if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
559 llvm_unreachable(
"Invalid SFixedLog2LMUL value!");
585 llvm_unreachable(
"Invalid LFixedLog2LMUL value, should be [-3, 3]");
589 }
else if (ComplexTT.first ==
"SEFixedLog2LMUL") {
591 if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
592 llvm_unreachable(
"Invalid SEFixedLog2LMUL value!");
618 llvm_unreachable(
"Invalid LFixedLog2LMUL value, should be [-3, 3]");
621 }
else if (ComplexTT.first ==
"Tuple") {
623 if (ComplexTT.second.getAsInteger(10, NF)) {
624 llvm_unreachable(
"Invalid NF value!");
629 llvm_unreachable(
"Illegal complex type transformers!");
632 PD.
VTM =
static_cast<uint8_t
>(
VTM);
636 for (
char I : PrototypeDescriptorStr) {
640 llvm_unreachable(
"'P' transformer cannot be used after 'C'");
642 llvm_unreachable(
"'P' transformer cannot be used twice");
664 llvm_unreachable(
"Illegal non-primitive type transformer!");
667 PD.
TM =
static_cast<uint8_t
>(
TM);
679 Scale = LMUL.
getScale(ElementBitwidth);
697 ElementBitwidth = 32;
707 ElementBitwidth *= 2;
709 Scale = LMUL.
getScale(ElementBitwidth);
712 ElementBitwidth *= 4;
714 Scale = LMUL.
getScale(ElementBitwidth);
717 ElementBitwidth *= 8;
719 Scale = LMUL.
getScale(ElementBitwidth);
723 Scale = LMUL.
getScale(ElementBitwidth);
751 applyFixedLog2LMUL(-3, FixedLMULType::LargerThan);
754 applyFixedLog2LMUL(-2, FixedLMULType::LargerThan);
757 applyFixedLog2LMUL(-1, FixedLMULType::LargerThan);
760 applyFixedLog2LMUL(0, FixedLMULType::LargerThan);
763 applyFixedLog2LMUL(1, FixedLMULType::LargerThan);
766 applyFixedLog2LMUL(2, FixedLMULType::LargerThan);
769 applyFixedLog2LMUL(3, FixedLMULType::LargerThan);
772 applyFixedLog2LMUL(-3, FixedLMULType::SmallerThan);
775 applyFixedLog2LMUL(-2, FixedLMULType::SmallerThan);
778 applyFixedLog2LMUL(-1, FixedLMULType::SmallerThan);
781 applyFixedLog2LMUL(0, FixedLMULType::SmallerThan);
784 applyFixedLog2LMUL(1, FixedLMULType::SmallerThan);
787 applyFixedLog2LMUL(2, FixedLMULType::SmallerThan);
790 applyFixedLog2LMUL(3, FixedLMULType::SmallerThan);
793 applyFixedLog2LMUL(-3, FixedLMULType::SmallerOrEqual);
796 applyFixedLog2LMUL(-2, FixedLMULType::SmallerOrEqual);
799 applyFixedLog2LMUL(-1, FixedLMULType::SmallerOrEqual);
802 applyFixedLog2LMUL(0, FixedLMULType::SmallerOrEqual);
805 applyFixedLog2LMUL(1, FixedLMULType::SmallerOrEqual);
808 applyFixedLog2LMUL(2, FixedLMULType::SmallerOrEqual);
811 applyFixedLog2LMUL(3, FixedLMULType::SmallerOrEqual);
821 NF = 2 +
static_cast<uint8_t
>(Transformer.
VTM) -
833 for (
unsigned TypeModifierMaskShift = 0;
835 ++TypeModifierMaskShift) {
836 unsigned TypeModifierMask = 1 << TypeModifierMaskShift;
837 if ((
static_cast<unsigned>(Transformer.
TM) & TypeModifierMask) !=
866 Scale = LMUL.
getScale(ElementBitwidth);
869 llvm_unreachable(
"Unknown type modifier mask!");
874void RVVType::applyLog2EEW(
unsigned Log2EEW) {
876 LMUL.
MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth));
878 ElementBitwidth = 1 << Log2EEW;
880 Scale = LMUL.
getScale(ElementBitwidth);
883void RVVType::applyFixedSEW(
unsigned NewSEW) {
885 if (ElementBitwidth == NewSEW) {
890 ElementBitwidth = NewSEW;
891 Scale = LMUL.
getScale(ElementBitwidth);
894void RVVType::applyFixedLog2LMUL(
int Log2LMUL,
enum FixedLMULType Type) {
896 case FixedLMULType::LargerThan:
902 case FixedLMULType::SmallerThan:
908 case FixedLMULType::SmallerOrEqual:
917 LMUL = LMULType(Log2LMUL);
918 Scale = LMUL.
getScale(ElementBitwidth);
921std::optional<RVVTypes>
941 assert(Log2LMUL >= -3 && Log2LMUL <= 3);
942 return (Log2LMUL + 3) | (
static_cast<uint64_t
>(BT) & 0xff) << 8 |
943 ((uint64_t)(Proto.
PT & 0xff) << 16) |
944 ((uint64_t)(Proto.
TM & 0xff) << 24) |
945 ((uint64_t)(Proto.
VTM & 0xff) << 32);
952 auto It = LegalTypes.find(Idx);
953 if (It != LegalTypes.end())
954 return &(It->second);
956 if (IllegalTypes.count(Idx))
963 std::pair<std::unordered_map<uint64_t, RVVType>::iterator,
bool>
964 InsertResult = LegalTypes.insert({Idx,
T});
965 return &(InsertResult.first->second);
968 IllegalTypes.insert(Idx);
976 StringRef NewName, StringRef Suffix, StringRef NewOverloadedName,
977 StringRef OverloadedSuffix, StringRef IRName,
bool IsMasked,
978 bool HasMaskedOffOperand,
bool HasVL,
PolicyScheme Scheme,
979 bool SupportOverloading,
bool HasBuiltinAlias, StringRef ManualCodegen,
980 const RVVTypes &OutInTypes,
const std::vector<int64_t> &NewIntrinsicTypes,
981 unsigned NF,
Policy NewPolicyAttrs,
bool HasFRMRoundModeOp)
982 : IRName(IRName), IsMasked(IsMasked),
983 HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme),
984 SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias),
985 ManualCodegen(ManualCodegen.str()), NF(NF), PolicyAttrs(NewPolicyAttrs) {
988 BuiltinName = NewName.str();
990 if (NewOverloadedName.empty())
991 OverloadedName = NewName.split(
"_").first.str();
993 OverloadedName = NewOverloadedName.str();
995 Name +=
"_" + Suffix.str();
996 if (!OverloadedSuffix.empty())
997 OverloadedName +=
"_" + OverloadedSuffix.str();
1000 PolicyAttrs, HasFRMRoundModeOp);
1003 OutputType = OutInTypes[0];
1004 InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
1008 IntrinsicTypes = NewIntrinsicTypes;
1011 for (
auto &I : IntrinsicTypes) {
1021 for (
const auto &
T : InputTypes) {
1022 S +=
T->getBuiltinStr();
1031 for (
auto PD : PrototypeDescriptors) {
1033 SuffixStrs.push_back((*T)->getShortStr());
1035 return join(SuffixStrs,
"_");
1040 bool HasMaskedOffOperand,
bool HasVL,
unsigned NF,
1047 if (HasMaskedOffOperand && !PolicyAttrs.
isTAMAPolicy()) {
1049 NewPrototype.insert(NewPrototype.begin() + 1, NewPrototype[0]);
1050 }
else if (NF > 1) {
1057 NewPrototype.insert(NewPrototype.begin() + 1, MaskoffType);
1065 NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1069 if (HasMaskedOffOperand && NF > 1) {
1076 NewPrototype.insert(NewPrototype.begin() + 1,
1079 NewPrototype.insert(NewPrototype.begin() + NF + 1,
1087 if (PolicyAttrs.
isTUPolicy() && HasPassthruOp)
1088 NewPrototype.insert(NewPrototype.begin(), NewPrototype[0]);
1089 }
else if (PolicyAttrs.
isTUPolicy() && HasPassthruOp) {
1096 NewPrototype.insert(NewPrototype.begin(), MaskoffType);
1105 NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1114 return NewPrototype;
1123 bool HasMaskPolicy) {
1124 if (HasTailPolicy && HasMaskPolicy)
1131 if (HasTailPolicy && !HasMaskPolicy)
1134 if (!HasTailPolicy && HasMaskPolicy)
1137 llvm_unreachable(
"An RVV instruction should not be without both tail policy "
1142 bool IsMasked,
bool HasPolicy, std::string &Name, std::string &BuiltinName,
1143 std::string &OverloadedName,
Policy &PolicyAttrs,
bool HasFRMRoundModeOp) {
1145 auto appendPolicySuffix = [&](
const std::string &suffix) {
1147 BuiltinName += suffix;
1148 OverloadedName += suffix;
1151 if (HasFRMRoundModeOp) {
1153 BuiltinName +=
"_rm";
1158 appendPolicySuffix(
"_tumu");
1160 appendPolicySuffix(
"_tum");
1162 appendPolicySuffix(
"_mu");
1165 BuiltinName +=
"_m";
1167 llvm_unreachable(
"Unhandled policy condition");
1170 appendPolicySuffix(
"_tu");
1174 llvm_unreachable(
"Unhandled policy condition");
1180 const StringRef Primaries(
"evwqom0ztulf");
1181 while (!Prototypes.empty()) {
1185 if (Prototypes[0] ==
'(')
1186 Idx = Prototypes.find_first_of(
')');
1187 Idx = Prototypes.find_first_of(Primaries, Idx);
1188 assert(Idx != StringRef::npos);
1190 Prototypes.slice(0, Idx + 1));
1192 llvm_unreachable(
"Error during parsing prototype.");
1193 PrototypeDescriptors.push_back(*PD);
1194 Prototypes = Prototypes.drop_front(Idx + 1);
1196 return PrototypeDescriptors;
1201 OS <<
"\"" <<
Record.Name <<
"\",";
1202 if (
Record.OverloadedName ==
nullptr ||
1203 StringRef(
Record.OverloadedName).empty())
1206 OS <<
"\"" <<
Record.OverloadedName <<
"\",";
1207 OS <<
Record.PrototypeIndex <<
",";
1208 OS <<
Record.SuffixIndex <<
",";
1209 OS <<
Record.OverloadedSuffixIndex <<
",";
1210 OS << (
int)
Record.PrototypeLength <<
",";
1211 OS << (
int)
Record.SuffixLength <<
",";
1212 OS << (
int)
Record.OverloadedSuffixSize <<
",";
1213 OS <<
Record.RequiredExtensions <<
",";
1214 OS << (
int)
Record.TypeRangeMask <<
",";
1216 OS << (
int)
Record.NF <<
",";
1218 OS << (
int)
Record.HasVL <<
",";
1219 OS << (
int)
Record.HasMaskedOffOperand <<
",";
1220 OS << (
int)
Record.HasTailPolicy <<
",";
1222 OS << (
int)
Record.HasFRMRoundModeOp <<
",";
1224 OS << (
int)
Record.UnMaskedPolicyScheme <<
",";
1225 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...
llvm::MachO::Record Record
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
bool hasPassthruOperand() const
static llvm::SmallVector< Policy > getSupportedMaskedPolicies(bool HasTailPolicy, bool HasMaskPolicy)
bool hasMaskedOffOperand() const
static llvm::SmallVector< PrototypeDescriptor > computeBuiltinTypes(llvm::ArrayRef< PrototypeDescriptor > Prototype, bool IsMasked, bool HasMaskedOffOperand, bool HasVL, unsigned NF, PolicyScheme DefaultScheme, Policy PolicyAttrs, bool IsTuple)
static void updateNamesAndPolicy(bool IsMasked, bool HasPolicy, std::string &Name, std::string &BuiltinName, std::string &OverloadedName, Policy &PolicyAttrs, bool HasFRMRoundModeOp)
static std::string getSuffixStr(RVVTypeCache &TypeCache, BasicType Type, int Log2LMUL, llvm::ArrayRef< PrototypeDescriptor > PrototypeDescriptors)
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, unsigned NF, Policy PolicyAttrs, bool HasFRMRoundModeOp)
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
static VectorTypeModifier getTupleVTM(unsigned NF)
std::vector< RVVTypePtr > RVVTypes
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
Diagnostic wrappers for TextAPI types for error reporting.
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