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";
253 ClangBuiltinStr +=
"uint";
256 ClangBuiltinStr +=
"float8e4m3" + LMUL.str() +
"_t";
259 ClangBuiltinStr +=
"float8e5m2" + LMUL.str() +
"_t";
262 llvm_unreachable(
"ScalarTypeKind is invalid");
264 ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.str() +
265 (IsTuple ?
"x" + utostr(NF) :
"") +
"_t";
268void RVVType::initTypeStr() {
269 assert(
isValid() &&
"RVVType is invalid");
276 return Twine(TypeStr + Twine(ElementBitwidth) +
"_t").str();
277 return Twine(
"v" + TypeStr + Twine(ElementBitwidth) + LMUL.str() +
278 (IsTuple ?
"x" + utostr(NF) :
"") +
"_t")
282 switch (ScalarType) {
295 Str =
"unsigned long";
306 Str +=
"vbool" + utostr(64 / *Scale) +
"_t";
310 if (ElementBitwidth == 64)
312 else if (ElementBitwidth == 32)
314 else if (ElementBitwidth == 16)
317 llvm_unreachable(
"Unhandled floating type.");
323 if (ElementBitwidth == 16)
326 llvm_unreachable(
"Unhandled floating type.");
337 Str +=
"vfloat8e4m3" + LMUL.str() +
"_t";
340 Str +=
"vfloat8e5m2" + LMUL.str() +
"_t";
343 llvm_unreachable(
"ScalarType is invalid!");
349void RVVType::initShortStr() {
350 switch (ScalarType) {
353 ShortStr =
"b" + utostr(64 / *Scale);
356 ShortStr =
"f" + utostr(ElementBitwidth);
359 ShortStr =
"bf" + utostr(ElementBitwidth);
362 ShortStr =
"i" + utostr(ElementBitwidth);
365 ShortStr =
"u" + utostr(ElementBitwidth);
374 llvm_unreachable(
"Unhandled case!");
377 ShortStr += LMUL.str();
379 ShortStr +=
"x" + utostr(NF);
383 assert(2 <= NF && NF <= 8 &&
"2 <= NF <= 8");
388void RVVType::applyBasicType() {
395 ElementBitwidth = 16;
399 ElementBitwidth = 32;
403 ElementBitwidth = 64;
407 ElementBitwidth = 16;
411 ElementBitwidth = 32;
415 ElementBitwidth = 64;
419 ElementBitwidth = 16;
431 llvm_unreachable(
"Unhandled type code!");
433 assert(ElementBitwidth != 0 &&
"Bad element bitwidth!");
436std::optional<PrototypeDescriptor>
438 llvm::StringRef PrototypeDescriptorStr) {
443 if (PrototypeDescriptorStr.empty())
447 auto PType = PrototypeDescriptorStr.back();
494 llvm_unreachable(
"Illegal primitive type transformers!");
497 PrototypeDescriptorStr = PrototypeDescriptorStr.drop_back();
500 if (PrototypeDescriptorStr.starts_with(
"(")) {
502 "VectorTypeModifier should only have one modifier");
503 size_t Idx = PrototypeDescriptorStr.find(
')');
504 assert(Idx != StringRef::npos);
505 StringRef
ComplexType = PrototypeDescriptorStr.slice(1, Idx);
506 PrototypeDescriptorStr = PrototypeDescriptorStr.drop_front(Idx + 1);
507 assert(!PrototypeDescriptorStr.contains(
'(') &&
508 "Only allow one vector type modifier");
511 if (ComplexTT.first ==
"Log2EEW") {
513 if (ComplexTT.second.getAsInteger(10, Log2EEW)) {
514 llvm_unreachable(
"Invalid Log2EEW value!");
531 llvm_unreachable(
"Invalid Log2EEW value, should be [3-6]");
534 }
else if (ComplexTT.first ==
"FixedSEW") {
536 if (ComplexTT.second.getAsInteger(10, NewSEW)) {
537 llvm_unreachable(
"Invalid FixedSEW value!");
554 llvm_unreachable(
"Invalid FixedSEW value, should be 8, 16, 32 or 64");
557 }
else if (ComplexTT.first ==
"LFixedLog2LMUL") {
559 if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
560 llvm_unreachable(
"Invalid LFixedLog2LMUL value!");
586 llvm_unreachable(
"Invalid LFixedLog2LMUL value, should be [-3, 3]");
589 }
else if (ComplexTT.first ==
"SFixedLog2LMUL") {
591 if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
592 llvm_unreachable(
"Invalid SFixedLog2LMUL value!");
618 llvm_unreachable(
"Invalid LFixedLog2LMUL value, should be [-3, 3]");
622 }
else if (ComplexTT.first ==
"SEFixedLog2LMUL") {
624 if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
625 llvm_unreachable(
"Invalid SEFixedLog2LMUL value!");
651 llvm_unreachable(
"Invalid LFixedLog2LMUL value, should be [-3, 3]");
654 }
else if (ComplexTT.first ==
"Tuple") {
656 if (ComplexTT.second.getAsInteger(10, NF)) {
657 llvm_unreachable(
"Invalid NF value!");
662 llvm_unreachable(
"Illegal complex type transformers!");
669 for (
char I : PrototypeDescriptorStr) {
673 llvm_unreachable(
"'P' transformer cannot be used after 'C'");
675 llvm_unreachable(
"'P' transformer cannot be used twice");
703 llvm_unreachable(
"Illegal non-primitive type transformer!");
718 Scale = LMUL.
getScale(ElementBitwidth);
736 ElementBitwidth = 32;
744 switch (
static_cast<VectorTypeModifier
>(Transformer.
VTM)) {
746 ElementBitwidth *= 2;
748 Scale = LMUL.
getScale(ElementBitwidth);
757 Scale = LMUL.
getScale(ElementBitwidth);
760 ElementBitwidth *= 4;
762 Scale = LMUL.
getScale(ElementBitwidth);
768 ElementBitwidth *= 8;
770 Scale = LMUL.
getScale(ElementBitwidth);
774 Scale = LMUL.
getScale(ElementBitwidth);
802 applyFixedLog2LMUL(-3, FixedLMULType::LargerThan);
805 applyFixedLog2LMUL(-2, FixedLMULType::LargerThan);
808 applyFixedLog2LMUL(-1, FixedLMULType::LargerThan);
811 applyFixedLog2LMUL(0, FixedLMULType::LargerThan);
814 applyFixedLog2LMUL(1, FixedLMULType::LargerThan);
817 applyFixedLog2LMUL(2, FixedLMULType::LargerThan);
820 applyFixedLog2LMUL(3, FixedLMULType::LargerThan);
823 applyFixedLog2LMUL(-3, FixedLMULType::SmallerThan);
826 applyFixedLog2LMUL(-2, FixedLMULType::SmallerThan);
829 applyFixedLog2LMUL(-1, FixedLMULType::SmallerThan);
832 applyFixedLog2LMUL(0, FixedLMULType::SmallerThan);
835 applyFixedLog2LMUL(1, FixedLMULType::SmallerThan);
838 applyFixedLog2LMUL(2, FixedLMULType::SmallerThan);
841 applyFixedLog2LMUL(3, FixedLMULType::SmallerThan);
844 applyFixedLog2LMUL(-3, FixedLMULType::SmallerOrEqual);
847 applyFixedLog2LMUL(-2, FixedLMULType::SmallerOrEqual);
850 applyFixedLog2LMUL(-1, FixedLMULType::SmallerOrEqual);
853 applyFixedLog2LMUL(0, FixedLMULType::SmallerOrEqual);
856 applyFixedLog2LMUL(1, FixedLMULType::SmallerOrEqual);
859 applyFixedLog2LMUL(2, FixedLMULType::SmallerOrEqual);
862 applyFixedLog2LMUL(3, FixedLMULType::SmallerOrEqual);
872 NF = 2 +
static_cast<uint8_t
>(Transformer.
VTM) -
884 for (
unsigned TypeModifierMaskShift = 0;
886 ++TypeModifierMaskShift) {
887 unsigned TypeModifierMask = 1 << TypeModifierMaskShift;
888 if ((
static_cast<unsigned>(Transformer.
TM) & TypeModifierMask) !=
917 Scale = LMUL.getScale(ElementBitwidth);
925 llvm_unreachable(
"AltFP8 modifier requires an OFP8 base type");
928 llvm_unreachable(
"Unknown type modifier mask!");
933void RVVType::applyLog2EEW(
unsigned Log2EEW) {
935 LMUL.MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth));
937 ElementBitwidth = 1 << Log2EEW;
939 Scale = LMUL.getScale(ElementBitwidth);
942void RVVType::applyFixedSEW(
unsigned NewSEW) {
944 if (ElementBitwidth == NewSEW) {
949 ElementBitwidth = NewSEW;
950 Scale = LMUL.getScale(ElementBitwidth);
953void RVVType::applyFixedLog2LMUL(
int Log2LMUL,
enum FixedLMULType
Type) {
955 case FixedLMULType::LargerThan:
956 if (Log2LMUL <= LMUL.Log2LMUL) {
961 case FixedLMULType::SmallerThan:
962 if (Log2LMUL >= LMUL.Log2LMUL) {
967 case FixedLMULType::SmallerOrEqual:
968 if (Log2LMUL > LMUL.Log2LMUL) {
976 LMUL = LMULType(Log2LMUL);
977 Scale = LMUL.getScale(ElementBitwidth);
980std::optional<RVVTypes>
1000 assert(Log2LMUL >= -3 && Log2LMUL <= 3);
1001 return (Log2LMUL + 3) | (
static_cast<uint64_t
>(BT) & 0xffff) << 8 |
1002 (
static_cast<uint64_t
>(Proto.
PT) << 24) |
1003 (
static_cast<uint64_t
>(Proto.
TM) << 32) |
1004 (
static_cast<uint64_t
>(Proto.
VTM) << 40);
1011 auto It = LegalTypes.find(Idx);
1012 if (It != LegalTypes.end())
1013 return &(It->second);
1015 if (IllegalTypes.count(Idx))
1016 return std::nullopt;
1019 RVVType T(BT, Log2LMUL, Proto);
1022 std::pair<std::unordered_map<uint64_t, RVVType>::iterator,
bool>
1023 InsertResult = LegalTypes.insert({Idx, T});
1024 return &(InsertResult.first->second);
1027 IllegalTypes.insert(Idx);
1028 return std::nullopt;
1035 StringRef NewName, StringRef Suffix, StringRef NewOverloadedName,
1036 StringRef OverloadedSuffix, StringRef IRName,
bool IsMasked,
1037 bool HasMaskedOffOperand,
bool HasVL,
PolicyScheme Scheme,
1038 bool SupportOverloading,
bool HasBuiltinAlias, StringRef ManualCodegen,
1039 const RVVTypes &OutInTypes,
const std::vector<int64_t> &NewIntrinsicTypes,
1040 unsigned NF,
bool HasSegInstSEW,
Policy NewPolicyAttrs,
1041 bool HasFRMRoundModeOp,
unsigned TWiden,
bool AltFmt)
1042 : IRName(IRName), IsMasked(IsMasked),
1043 HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme),
1044 SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias),
1045 ManualCodegen(ManualCodegen.str()), NF(NF), HasSegInstSEW(HasSegInstSEW),
1046 PolicyAttrs(NewPolicyAttrs), TWiden(TWiden) {
1049 BuiltinName = NewName.str();
1051 if (NewOverloadedName.empty())
1052 OverloadedName = NewName.split(
"_").first.str();
1054 OverloadedName = NewOverloadedName.str();
1055 if (!Suffix.empty())
1056 Name +=
"_" + Suffix.str();
1057 if (!OverloadedSuffix.empty())
1058 OverloadedName +=
"_" + OverloadedSuffix.str();
1061 PolicyAttrs, HasFRMRoundModeOp, AltFmt);
1064 OutputType = OutInTypes[0];
1065 InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
1069 IntrinsicTypes = NewIntrinsicTypes;
1072 for (
auto &I : IntrinsicTypes) {
1081 S += OutputType->getBuiltinStr();
1082 for (
const auto &T : InputTypes) {
1083 S += T->getBuiltinStr();
1092 for (
auto PD : PrototypeDescriptors) {
1094 SuffixStrs.push_back((*T)->getShortStr());
1096 return join(SuffixStrs,
"_");
1101 bool HasMaskedOffOperand,
bool HasVL,
unsigned NF,
1108 if (HasMaskedOffOperand && !PolicyAttrs.isTAMAPolicy()) {
1110 NewPrototype.insert(NewPrototype.begin() + 1, NewPrototype[0]);
1111 }
else if (NF > 1) {
1117 NewPrototype.insert(NewPrototype.begin() + 1, MaskoffType);
1125 NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1129 if (HasMaskedOffOperand && NF > 1) {
1136 NewPrototype.insert(NewPrototype.begin() + 1,
1139 NewPrototype.insert(NewPrototype.begin() + NF + 1,
1147 if (PolicyAttrs.isTUPolicy() && HasPassthruOp)
1148 NewPrototype.insert(NewPrototype.begin(), NewPrototype[0]);
1149 }
else if (PolicyAttrs.isTUPolicy() && HasPassthruOp) {
1155 NewPrototype.insert(NewPrototype.begin(), MaskoffType);
1164 NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1173 return NewPrototype;
1182 bool HasMaskPolicy) {
1183 if (HasTailPolicy && HasMaskPolicy)
1190 if (HasTailPolicy && !HasMaskPolicy)
1193 if (!HasTailPolicy && HasMaskPolicy)
1196 llvm_unreachable(
"An RVV instruction should not be without both tail policy "
1202 std::string &BuiltinName,
1203 std::string &OverloadedName,
1205 bool HasFRMRoundModeOp,
bool AltFmt) {
1207 auto appendPolicySuffix = [&](
const std::string &suffix) {
1209 BuiltinName += suffix;
1210 OverloadedName += suffix;
1213 if (HasFRMRoundModeOp) {
1215 BuiltinName +=
"_rm";
1219 BuiltinName +=
"_alt";
1222 if (PolicyAttrs.isTUMUPolicy())
1223 appendPolicySuffix(
"_tumu");
1224 else if (PolicyAttrs.isTUMAPolicy())
1225 appendPolicySuffix(
"_tum");
1226 else if (PolicyAttrs.isTAMUPolicy())
1227 appendPolicySuffix(
"_mu");
1228 else if (PolicyAttrs.isTAMAPolicy()) {
1230 BuiltinName +=
"_m";
1232 llvm_unreachable(
"Unhandled policy condition");
1234 if (PolicyAttrs.isTUPolicy())
1235 appendPolicySuffix(
"_tu");
1236 else if (PolicyAttrs.isTAPolicy())
1239 llvm_unreachable(
"Unhandled policy condition");
1245 const StringRef Primaries(
"evwdqom0ztulf");
1246 while (!Prototypes.empty()) {
1250 if (Prototypes[0] ==
'(')
1251 Idx = Prototypes.find_first_of(
')');
1252 Idx = Prototypes.find_first_of(Primaries, Idx);
1253 assert(Idx != StringRef::npos);
1255 Prototypes.slice(0, Idx + 1));
1257 llvm_unreachable(
"Error during parsing prototype.");
1258 PrototypeDescriptors.push_back(*PD);
1259 Prototypes = Prototypes.drop_front(Idx + 1);
1261 return PrototypeDescriptors;
1264#define STRINGIFY(NAME) \
1282 OS <<
"/*Name=*/\"" <<
Record.Name <<
"\", ";
1283 if (
Record.OverloadedName ==
nullptr ||
1284 StringRef(
Record.OverloadedName).empty())
1285 OS <<
"/*OverloadedName=*/nullptr, ";
1287 OS <<
"/*OverloadedName=*/\"" <<
Record.OverloadedName <<
"\", ";
1288 OS <<
"/*RequiredExtensions=*/\"" <<
Record.RequiredExtensions <<
"\", ";
1289 OS <<
"/*PrototypeIndex=*/" <<
Record.PrototypeIndex <<
", ";
1290 OS <<
"/*SuffixIndex=*/" <<
Record.SuffixIndex <<
", ";
1291 OS <<
"/*OverloadedSuffixIndex=*/" <<
Record.OverloadedSuffixIndex <<
", ";
1292 OS <<
"/*PrototypeLength=*/" << (int)
Record.PrototypeLength <<
", ";
1293 OS <<
"/*SuffixLength=*/" << (int)
Record.SuffixLength <<
", ";
1294 OS <<
"/*OverloadedSuffixSize=*/" << (int)
Record.OverloadedSuffixSize <<
", ";
1295 OS <<
"/*TypeRangeMask=*/" << (int)
Record.TypeRangeMask <<
", ";
1296 OS <<
"/*Log2LMULMask=*/" << (int)
Record.Log2LMULMask <<
", ";
1297 OS <<
"/*NF=*/" << (int)
Record.NF <<
", ";
1298 OS <<
"/*HasMasked=*/" << (int)
Record.HasMasked <<
", ";
1299 OS <<
"/*HasVL=*/" << (int)
Record.HasVL <<
", ";
1300 OS <<
"/*HasMaskedOffOperand=*/" << (int)
Record.HasMaskedOffOperand <<
", ";
1301 OS <<
"/*HasTailPolicy=*/" << (int)
Record.HasTailPolicy <<
", ";
1302 OS <<
"/*HasMaskPolicy=*/" << (int)
Record.HasMaskPolicy <<
", ";
1303 OS <<
"/*HasFRMRoundModeOp=*/" << (int)
Record.HasFRMRoundModeOp <<
", ";
1304 OS <<
"/*AltFmt=*/" << (int)
Record.AltFmt <<
",";
1305 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.
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, bool HasSegInstSEW, Policy PolicyAttrs, bool HasFRMRoundModeOp, unsigned TWiden, bool AltFmt)
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)
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