10#include "llvm/ADT/ArrayRef.h"
11#include "llvm/ADT/StringExtras.h"
12#include "llvm/ADT/Twine.h"
13#include "llvm/Support/ErrorHandling.h"
14#include "llvm/Support/raw_ostream.h"
35 assert(NewLog2LMUL <= 3 && NewLog2LMUL >= -3 &&
"Bad LMUL number!");
41 return "mf" + utostr(1ULL << (-
Log2LMUL));
42 return "m" + utostr(1ULL <<
Log2LMUL);
46 int Log2ScaleResult = 0;
47 switch (ElementBitwidth) {
64 if (Log2ScaleResult < 0)
66 return 1 << Log2ScaleResult;
71RVVType::RVVType(
BasicType BT,
int Log2LMUL,
75 applyModifier(prototype);
81 initClangBuiltinStr();
104bool RVVType::verifyType()
const {
111 if (
isFloat() && ElementBitwidth == 8)
113 if (
isBFloat() && ElementBitwidth != 16)
115 if (IsTuple && (NF == 1 || NF > 8))
117 if (IsTuple && (1 << std::max(0, LMUL.Log2LMUL)) * NF > 8)
120 switch (ElementBitwidth) {
124 return (
V <= 64 && isPowerOf2_32(
V));
127 return (
V <= 32 && isPowerOf2_32(
V));
130 return (
V <= 16 && isPowerOf2_32(
V));
133 return (
V <= 8 && isPowerOf2_32(
V));
138void RVVType::initBuiltinStr() {
139 assert(
isValid() &&
"RVVType is invalid");
140 switch (ScalarType) {
147 BuiltinStr =
"I" + BuiltinStr;
161 assert(ElementBitwidth == 1);
166 switch (ElementBitwidth) {
180 llvm_unreachable(
"Unhandled ElementBitwidth!");
183 BuiltinStr =
"S" + BuiltinStr;
185 BuiltinStr =
"U" + BuiltinStr;
188 switch (ElementBitwidth) {
199 llvm_unreachable(
"Unhandled ElementBitwidth!");
212 llvm_unreachable(
"ScalarType is invalid!");
215 BuiltinStr =
"I" + BuiltinStr;
223 BuiltinStr =
"q" + utostr(*Scale) + BuiltinStr;
231 BuiltinStr =
"T" + utostr(NF) + BuiltinStr;
234void RVVType::initClangBuiltinStr() {
235 assert(
isValid() &&
"RVVType is invalid");
236 assert(
isVector() &&
"Handle Vector type only");
238 ClangBuiltinStr =
"__rvv_";
239 switch (ScalarType) {
241 ClangBuiltinStr +=
"bool" + utostr(64 / *Scale) +
"_t";
244 ClangBuiltinStr +=
"float";
247 ClangBuiltinStr +=
"bfloat";
250 ClangBuiltinStr +=
"int";
255 ClangBuiltinStr +=
"uint";
258 llvm_unreachable(
"ScalarTypeKind is invalid");
260 ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.str() +
261 (IsTuple ?
"x" + utostr(NF) :
"") +
"_t";
264void RVVType::initTypeStr() {
265 assert(
isValid() &&
"RVVType is invalid");
272 return Twine(TypeStr + Twine(ElementBitwidth) +
"_t").str();
273 return Twine(
"v" + TypeStr + Twine(ElementBitwidth) + LMUL.str() +
274 (IsTuple ?
"x" + utostr(NF) :
"") +
"_t")
278 switch (ScalarType) {
291 Str =
"unsigned long";
302 Str +=
"vbool" + utostr(64 / *Scale) +
"_t";
306 if (ElementBitwidth == 64)
308 else if (ElementBitwidth == 32)
310 else if (ElementBitwidth == 16)
313 llvm_unreachable(
"Unhandled floating type.");
319 if (ElementBitwidth == 16)
322 llvm_unreachable(
"Unhandled floating type.");
335 llvm_unreachable(
"ScalarType is invalid!");
341void RVVType::initShortStr() {
342 switch (ScalarType) {
345 ShortStr =
"b" + utostr(64 / *Scale);
348 ShortStr =
"f" + utostr(ElementBitwidth);
351 ShortStr =
"bf" + utostr(ElementBitwidth);
354 ShortStr =
"i" + utostr(ElementBitwidth);
357 ShortStr =
"u" + utostr(ElementBitwidth);
366 llvm_unreachable(
"Unhandled case!");
369 ShortStr += LMUL.str();
371 ShortStr +=
"x" + utostr(NF);
375 assert(2 <= NF && NF <= 8 &&
"2 <= NF <= 8");
380void RVVType::applyBasicType() {
387 ElementBitwidth = 16;
391 ElementBitwidth = 32;
395 ElementBitwidth = 64;
399 ElementBitwidth = 16;
403 ElementBitwidth = 32;
407 ElementBitwidth = 64;
411 ElementBitwidth = 16;
423 llvm_unreachable(
"Unhandled type code!");
425 assert(ElementBitwidth != 0 &&
"Bad element bitwidth!");
428std::optional<PrototypeDescriptor>
430 llvm::StringRef PrototypeDescriptorStr) {
435 if (PrototypeDescriptorStr.empty())
439 auto PType = PrototypeDescriptorStr.back();
486 llvm_unreachable(
"Illegal primitive type transformers!");
489 PrototypeDescriptorStr = PrototypeDescriptorStr.drop_back();
492 if (PrototypeDescriptorStr.starts_with(
"(")) {
494 "VectorTypeModifier should only have one modifier");
495 size_t Idx = PrototypeDescriptorStr.find(
')');
496 assert(Idx != StringRef::npos);
497 StringRef
ComplexType = PrototypeDescriptorStr.slice(1, Idx);
498 PrototypeDescriptorStr = PrototypeDescriptorStr.drop_front(Idx + 1);
499 assert(!PrototypeDescriptorStr.contains(
'(') &&
500 "Only allow one vector type modifier");
503 if (ComplexTT.first ==
"Log2EEW") {
505 if (ComplexTT.second.getAsInteger(10, Log2EEW)) {
506 llvm_unreachable(
"Invalid Log2EEW value!");
523 llvm_unreachable(
"Invalid Log2EEW value, should be [3-6]");
526 }
else if (ComplexTT.first ==
"FixedSEW") {
528 if (ComplexTT.second.getAsInteger(10, NewSEW)) {
529 llvm_unreachable(
"Invalid FixedSEW value!");
546 llvm_unreachable(
"Invalid FixedSEW value, should be 8, 16, 32 or 64");
549 }
else if (ComplexTT.first ==
"LFixedLog2LMUL") {
551 if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
552 llvm_unreachable(
"Invalid LFixedLog2LMUL value!");
578 llvm_unreachable(
"Invalid LFixedLog2LMUL value, should be [-3, 3]");
581 }
else if (ComplexTT.first ==
"SFixedLog2LMUL") {
583 if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
584 llvm_unreachable(
"Invalid SFixedLog2LMUL value!");
610 llvm_unreachable(
"Invalid LFixedLog2LMUL value, should be [-3, 3]");
614 }
else if (ComplexTT.first ==
"SEFixedLog2LMUL") {
616 if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
617 llvm_unreachable(
"Invalid SEFixedLog2LMUL value!");
643 llvm_unreachable(
"Invalid LFixedLog2LMUL value, should be [-3, 3]");
646 }
else if (ComplexTT.first ==
"Tuple") {
648 if (ComplexTT.second.getAsInteger(10, NF)) {
649 llvm_unreachable(
"Invalid NF value!");
654 llvm_unreachable(
"Illegal complex type transformers!");
661 for (
char I : PrototypeDescriptorStr) {
665 llvm_unreachable(
"'P' transformer cannot be used after 'C'");
667 llvm_unreachable(
"'P' transformer cannot be used twice");
692 llvm_unreachable(
"Illegal non-primitive type transformer!");
707 Scale = LMUL.
getScale(ElementBitwidth);
725 ElementBitwidth = 32;
733 switch (
static_cast<VectorTypeModifier
>(Transformer.
VTM)) {
735 ElementBitwidth *= 2;
737 Scale = LMUL.
getScale(ElementBitwidth);
746 Scale = LMUL.
getScale(ElementBitwidth);
749 ElementBitwidth *= 4;
751 Scale = LMUL.
getScale(ElementBitwidth);
757 ElementBitwidth *= 8;
759 Scale = LMUL.
getScale(ElementBitwidth);
763 Scale = LMUL.
getScale(ElementBitwidth);
791 applyFixedLog2LMUL(-3, FixedLMULType::LargerThan);
794 applyFixedLog2LMUL(-2, FixedLMULType::LargerThan);
797 applyFixedLog2LMUL(-1, FixedLMULType::LargerThan);
800 applyFixedLog2LMUL(0, FixedLMULType::LargerThan);
803 applyFixedLog2LMUL(1, FixedLMULType::LargerThan);
806 applyFixedLog2LMUL(2, FixedLMULType::LargerThan);
809 applyFixedLog2LMUL(3, FixedLMULType::LargerThan);
812 applyFixedLog2LMUL(-3, FixedLMULType::SmallerThan);
815 applyFixedLog2LMUL(-2, FixedLMULType::SmallerThan);
818 applyFixedLog2LMUL(-1, FixedLMULType::SmallerThan);
821 applyFixedLog2LMUL(0, FixedLMULType::SmallerThan);
824 applyFixedLog2LMUL(1, FixedLMULType::SmallerThan);
827 applyFixedLog2LMUL(2, FixedLMULType::SmallerThan);
830 applyFixedLog2LMUL(3, FixedLMULType::SmallerThan);
833 applyFixedLog2LMUL(-3, FixedLMULType::SmallerOrEqual);
836 applyFixedLog2LMUL(-2, FixedLMULType::SmallerOrEqual);
839 applyFixedLog2LMUL(-1, FixedLMULType::SmallerOrEqual);
842 applyFixedLog2LMUL(0, FixedLMULType::SmallerOrEqual);
845 applyFixedLog2LMUL(1, FixedLMULType::SmallerOrEqual);
848 applyFixedLog2LMUL(2, FixedLMULType::SmallerOrEqual);
851 applyFixedLog2LMUL(3, FixedLMULType::SmallerOrEqual);
861 NF = 2 +
static_cast<uint8_t
>(Transformer.
VTM) -
873 for (
unsigned TypeModifierMaskShift = 0;
875 ++TypeModifierMaskShift) {
876 unsigned TypeModifierMask = 1 << TypeModifierMaskShift;
877 if ((
static_cast<unsigned>(Transformer.
TM) & TypeModifierMask) !=
906 Scale = LMUL.getScale(ElementBitwidth);
909 llvm_unreachable(
"Unknown type modifier mask!");
914void RVVType::applyLog2EEW(
unsigned Log2EEW) {
916 LMUL.MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth));
918 ElementBitwidth = 1 << Log2EEW;
920 Scale = LMUL.getScale(ElementBitwidth);
923void RVVType::applyFixedSEW(
unsigned NewSEW) {
925 if (ElementBitwidth == NewSEW) {
930 ElementBitwidth = NewSEW;
931 Scale = LMUL.getScale(ElementBitwidth);
934void RVVType::applyFixedLog2LMUL(
int Log2LMUL,
enum FixedLMULType
Type) {
936 case FixedLMULType::LargerThan:
937 if (Log2LMUL <= LMUL.Log2LMUL) {
942 case FixedLMULType::SmallerThan:
943 if (Log2LMUL >= LMUL.Log2LMUL) {
948 case FixedLMULType::SmallerOrEqual:
949 if (Log2LMUL > LMUL.Log2LMUL) {
957 LMUL = LMULType(Log2LMUL);
958 Scale = LMUL.getScale(ElementBitwidth);
961std::optional<RVVTypes>
981 assert(Log2LMUL >= -3 && Log2LMUL <= 3);
982 return (Log2LMUL + 3) | (
static_cast<uint64_t
>(BT) & 0xffff) << 8 |
983 (
static_cast<uint64_t
>(Proto.
PT) << 24) |
984 (
static_cast<uint64_t
>(Proto.
TM) << 32) |
985 (
static_cast<uint64_t
>(Proto.
VTM) << 40);
992 auto It = LegalTypes.find(Idx);
993 if (It != LegalTypes.end())
994 return &(It->second);
996 if (IllegalTypes.count(Idx))
1000 RVVType T(BT, Log2LMUL, Proto);
1003 std::pair<std::unordered_map<uint64_t, RVVType>::iterator,
bool>
1004 InsertResult = LegalTypes.insert({Idx, T});
1005 return &(InsertResult.first->second);
1008 IllegalTypes.insert(Idx);
1009 return std::nullopt;
1016 StringRef NewOverloadedName,
1017 StringRef OverloadedSuffix, StringRef IRName,
1018 bool IsMasked,
bool HasMaskedOffOperand,
bool HasVL,
1020 bool HasBuiltinAlias, StringRef ManualCodegen,
1022 const std::vector<int64_t> &NewIntrinsicTypes,
1023 unsigned NF,
Policy NewPolicyAttrs,
1024 bool HasFRMRoundModeOp,
unsigned TWiden,
bool AltFmt)
1025 : IRName(IRName), IsMasked(IsMasked),
1026 HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme),
1027 SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias),
1028 ManualCodegen(ManualCodegen.str()), NF(NF), PolicyAttrs(NewPolicyAttrs),
1032 BuiltinName = NewName.str();
1034 if (NewOverloadedName.empty())
1035 OverloadedName = NewName.split(
"_").first.str();
1037 OverloadedName = NewOverloadedName.str();
1038 if (!Suffix.empty())
1039 Name +=
"_" + Suffix.str();
1040 if (!OverloadedSuffix.empty())
1041 OverloadedName +=
"_" + OverloadedSuffix.str();
1044 PolicyAttrs, HasFRMRoundModeOp, AltFmt);
1047 OutputType = OutInTypes[0];
1048 InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
1052 IntrinsicTypes = NewIntrinsicTypes;
1055 for (
auto &I : IntrinsicTypes) {
1064 S += OutputType->getBuiltinStr();
1065 for (
const auto &T : InputTypes) {
1066 S += T->getBuiltinStr();
1075 for (
auto PD : PrototypeDescriptors) {
1077 SuffixStrs.push_back((*T)->getShortStr());
1079 return join(SuffixStrs,
"_");
1084 bool HasMaskedOffOperand,
bool HasVL,
unsigned NF,
1091 if (HasMaskedOffOperand && !PolicyAttrs.isTAMAPolicy()) {
1093 NewPrototype.insert(NewPrototype.begin() + 1, NewPrototype[0]);
1094 }
else if (NF > 1) {
1100 NewPrototype.insert(NewPrototype.begin() + 1, MaskoffType);
1108 NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1112 if (HasMaskedOffOperand && NF > 1) {
1119 NewPrototype.insert(NewPrototype.begin() + 1,
1122 NewPrototype.insert(NewPrototype.begin() + NF + 1,
1130 if (PolicyAttrs.isTUPolicy() && HasPassthruOp)
1131 NewPrototype.insert(NewPrototype.begin(), NewPrototype[0]);
1132 }
else if (PolicyAttrs.isTUPolicy() && HasPassthruOp) {
1138 NewPrototype.insert(NewPrototype.begin(), MaskoffType);
1147 NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1156 return NewPrototype;
1165 bool HasMaskPolicy) {
1166 if (HasTailPolicy && HasMaskPolicy)
1173 if (HasTailPolicy && !HasMaskPolicy)
1176 if (!HasTailPolicy && HasMaskPolicy)
1179 llvm_unreachable(
"An RVV instruction should not be without both tail policy "
1185 std::string &BuiltinName,
1186 std::string &OverloadedName,
1188 bool HasFRMRoundModeOp,
bool AltFmt) {
1190 auto appendPolicySuffix = [&](
const std::string &suffix) {
1192 BuiltinName += suffix;
1193 OverloadedName += suffix;
1196 if (HasFRMRoundModeOp) {
1198 BuiltinName +=
"_rm";
1202 BuiltinName +=
"_alt";
1205 if (PolicyAttrs.isTUMUPolicy())
1206 appendPolicySuffix(
"_tumu");
1207 else if (PolicyAttrs.isTUMAPolicy())
1208 appendPolicySuffix(
"_tum");
1209 else if (PolicyAttrs.isTAMUPolicy())
1210 appendPolicySuffix(
"_mu");
1211 else if (PolicyAttrs.isTAMAPolicy()) {
1213 BuiltinName +=
"_m";
1215 llvm_unreachable(
"Unhandled policy condition");
1217 if (PolicyAttrs.isTUPolicy())
1218 appendPolicySuffix(
"_tu");
1219 else if (PolicyAttrs.isTAPolicy())
1222 llvm_unreachable(
"Unhandled policy condition");
1228 const StringRef Primaries(
"evwdqom0ztulf");
1229 while (!Prototypes.empty()) {
1233 if (Prototypes[0] ==
'(')
1234 Idx = Prototypes.find_first_of(
')');
1235 Idx = Prototypes.find_first_of(Primaries, Idx);
1236 assert(Idx != StringRef::npos);
1238 Prototypes.slice(0, Idx + 1));
1240 llvm_unreachable(
"Error during parsing prototype.");
1241 PrototypeDescriptors.push_back(*PD);
1242 Prototypes = Prototypes.drop_front(Idx + 1);
1244 return PrototypeDescriptors;
1247#define STRINGIFY(NAME) \
1265 OS <<
"/*Name=*/\"" <<
Record.Name <<
"\", ";
1266 if (
Record.OverloadedName ==
nullptr ||
1267 StringRef(
Record.OverloadedName).empty())
1268 OS <<
"/*OverloadedName=*/nullptr, ";
1270 OS <<
"/*OverloadedName=*/\"" <<
Record.OverloadedName <<
"\", ";
1271 OS <<
"/*RequiredExtensions=*/\"" <<
Record.RequiredExtensions <<
"\", ";
1272 OS <<
"/*PrototypeIndex=*/" <<
Record.PrototypeIndex <<
", ";
1273 OS <<
"/*SuffixIndex=*/" <<
Record.SuffixIndex <<
", ";
1274 OS <<
"/*OverloadedSuffixIndex=*/" <<
Record.OverloadedSuffixIndex <<
", ";
1275 OS <<
"/*PrototypeLength=*/" << (int)
Record.PrototypeLength <<
", ";
1276 OS <<
"/*SuffixLength=*/" << (int)
Record.SuffixLength <<
", ";
1277 OS <<
"/*OverloadedSuffixSize=*/" << (int)
Record.OverloadedSuffixSize <<
", ";
1278 OS <<
"/*TypeRangeMask=*/" << (int)
Record.TypeRangeMask <<
", ";
1279 OS <<
"/*Log2LMULMask=*/" << (int)
Record.Log2LMULMask <<
", ";
1280 OS <<
"/*NF=*/" << (int)
Record.NF <<
", ";
1281 OS <<
"/*HasMasked=*/" << (int)
Record.HasMasked <<
", ";
1282 OS <<
"/*HasVL=*/" << (int)
Record.HasVL <<
", ";
1283 OS <<
"/*HasMaskedOffOperand=*/" << (int)
Record.HasMaskedOffOperand <<
", ";
1284 OS <<
"/*HasTailPolicy=*/" << (int)
Record.HasTailPolicy <<
", ";
1285 OS <<
"/*HasMaskPolicy=*/" << (int)
Record.HasMaskPolicy <<
", ";
1286 OS <<
"/*HasFRMRoundModeOp=*/" << (int)
Record.HasFRMRoundModeOp <<
", ";
1287 OS <<
"/*AltFmt=*/" << (int)
Record.AltFmt <<
",";
1288 OS <<
"/*IsTuple=*/" << (int)
Record.IsTuple <<
", ";
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 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 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, unsigned TWiden, bool AltFmt)
static void updateNamesAndPolicy(bool IsMasked, bool HasPolicy, std::string &Name, std::string &BuiltinName, std::string &OverloadedName, Policy &PolicyAttrs, bool HasFRMRoundModeOp, bool AltFmt)
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
The base class of the type hierarchy.
std::optional< unsigned > VScaleVal
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, enum PolicyScheme PS)
llvm::SmallVector< PrototypeDescriptor > parsePrototypes(llvm::StringRef Prototypes)
std::vector< RVVTypePtr > RVVTypes
static uint64_t computeRVVTypeHashValue(BasicType BT, int Log2LMUL, PrototypeDescriptor Proto)
static VectorTypeModifier getTupleVTM(unsigned NF)
The JSON file list parser is used to communicate input to InstallAPI.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ Type
The name was classified as a type.
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
constexpr PrototypeDescriptor()=default
static const PrototypeDescriptor Mask
static const PrototypeDescriptor Vector