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");
700 llvm_unreachable(
"Illegal non-primitive type transformer!");
715 Scale = LMUL.
getScale(ElementBitwidth);
733 ElementBitwidth = 32;
741 switch (
static_cast<VectorTypeModifier
>(Transformer.
VTM)) {
743 ElementBitwidth *= 2;
745 Scale = LMUL.
getScale(ElementBitwidth);
754 Scale = LMUL.
getScale(ElementBitwidth);
757 ElementBitwidth *= 4;
759 Scale = LMUL.
getScale(ElementBitwidth);
765 ElementBitwidth *= 8;
767 Scale = LMUL.
getScale(ElementBitwidth);
771 Scale = LMUL.
getScale(ElementBitwidth);
799 applyFixedLog2LMUL(-3, FixedLMULType::LargerThan);
802 applyFixedLog2LMUL(-2, FixedLMULType::LargerThan);
805 applyFixedLog2LMUL(-1, FixedLMULType::LargerThan);
808 applyFixedLog2LMUL(0, FixedLMULType::LargerThan);
811 applyFixedLog2LMUL(1, FixedLMULType::LargerThan);
814 applyFixedLog2LMUL(2, FixedLMULType::LargerThan);
817 applyFixedLog2LMUL(3, FixedLMULType::LargerThan);
820 applyFixedLog2LMUL(-3, FixedLMULType::SmallerThan);
823 applyFixedLog2LMUL(-2, FixedLMULType::SmallerThan);
826 applyFixedLog2LMUL(-1, FixedLMULType::SmallerThan);
829 applyFixedLog2LMUL(0, FixedLMULType::SmallerThan);
832 applyFixedLog2LMUL(1, FixedLMULType::SmallerThan);
835 applyFixedLog2LMUL(2, FixedLMULType::SmallerThan);
838 applyFixedLog2LMUL(3, FixedLMULType::SmallerThan);
841 applyFixedLog2LMUL(-3, FixedLMULType::SmallerOrEqual);
844 applyFixedLog2LMUL(-2, FixedLMULType::SmallerOrEqual);
847 applyFixedLog2LMUL(-1, FixedLMULType::SmallerOrEqual);
850 applyFixedLog2LMUL(0, FixedLMULType::SmallerOrEqual);
853 applyFixedLog2LMUL(1, FixedLMULType::SmallerOrEqual);
856 applyFixedLog2LMUL(2, FixedLMULType::SmallerOrEqual);
859 applyFixedLog2LMUL(3, FixedLMULType::SmallerOrEqual);
869 NF = 2 +
static_cast<uint8_t
>(Transformer.
VTM) -
881 for (
unsigned TypeModifierMaskShift = 0;
883 ++TypeModifierMaskShift) {
884 unsigned TypeModifierMask = 1 << TypeModifierMaskShift;
885 if ((
static_cast<unsigned>(Transformer.
TM) & TypeModifierMask) !=
914 Scale = LMUL.getScale(ElementBitwidth);
917 llvm_unreachable(
"Unknown type modifier mask!");
922void RVVType::applyLog2EEW(
unsigned Log2EEW) {
924 LMUL.MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth));
926 ElementBitwidth = 1 << Log2EEW;
928 Scale = LMUL.getScale(ElementBitwidth);
931void RVVType::applyFixedSEW(
unsigned NewSEW) {
933 if (ElementBitwidth == NewSEW) {
938 ElementBitwidth = NewSEW;
939 Scale = LMUL.getScale(ElementBitwidth);
942void RVVType::applyFixedLog2LMUL(
int Log2LMUL,
enum FixedLMULType
Type) {
944 case FixedLMULType::LargerThan:
945 if (Log2LMUL <= LMUL.Log2LMUL) {
950 case FixedLMULType::SmallerThan:
951 if (Log2LMUL >= LMUL.Log2LMUL) {
956 case FixedLMULType::SmallerOrEqual:
957 if (Log2LMUL > LMUL.Log2LMUL) {
965 LMUL = LMULType(Log2LMUL);
966 Scale = LMUL.getScale(ElementBitwidth);
969std::optional<RVVTypes>
989 assert(Log2LMUL >= -3 && Log2LMUL <= 3);
990 return (Log2LMUL + 3) | (
static_cast<uint64_t
>(BT) & 0xffff) << 8 |
991 (
static_cast<uint64_t
>(Proto.
PT) << 24) |
992 (
static_cast<uint64_t
>(Proto.
TM) << 32) |
993 (
static_cast<uint64_t
>(Proto.
VTM) << 40);
1000 auto It = LegalTypes.find(Idx);
1001 if (It != LegalTypes.end())
1002 return &(It->second);
1004 if (IllegalTypes.count(Idx))
1005 return std::nullopt;
1008 RVVType T(BT, Log2LMUL, Proto);
1011 std::pair<std::unordered_map<uint64_t, RVVType>::iterator,
bool>
1012 InsertResult = LegalTypes.insert({Idx, T});
1013 return &(InsertResult.first->second);
1016 IllegalTypes.insert(Idx);
1017 return std::nullopt;
1024 StringRef NewName, StringRef Suffix, StringRef NewOverloadedName,
1025 StringRef OverloadedSuffix, StringRef IRName,
bool IsMasked,
1026 bool HasMaskedOffOperand,
bool HasVL,
PolicyScheme Scheme,
1027 bool SupportOverloading,
bool HasBuiltinAlias, StringRef ManualCodegen,
1028 const RVVTypes &OutInTypes,
const std::vector<int64_t> &NewIntrinsicTypes,
1029 unsigned NF,
bool HasSegInstSEW,
Policy NewPolicyAttrs,
1030 bool HasFRMRoundModeOp,
unsigned TWiden,
bool AltFmt)
1031 : IRName(IRName), IsMasked(IsMasked),
1032 HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme),
1033 SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias),
1034 ManualCodegen(ManualCodegen.str()), NF(NF), HasSegInstSEW(HasSegInstSEW),
1035 PolicyAttrs(NewPolicyAttrs), TWiden(TWiden) {
1038 BuiltinName = NewName.str();
1040 if (NewOverloadedName.empty())
1041 OverloadedName = NewName.split(
"_").first.str();
1043 OverloadedName = NewOverloadedName.str();
1044 if (!Suffix.empty())
1045 Name +=
"_" + Suffix.str();
1046 if (!OverloadedSuffix.empty())
1047 OverloadedName +=
"_" + OverloadedSuffix.str();
1050 PolicyAttrs, HasFRMRoundModeOp, AltFmt);
1053 OutputType = OutInTypes[0];
1054 InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
1058 IntrinsicTypes = NewIntrinsicTypes;
1061 for (
auto &I : IntrinsicTypes) {
1070 S += OutputType->getBuiltinStr();
1071 for (
const auto &T : InputTypes) {
1072 S += T->getBuiltinStr();
1081 for (
auto PD : PrototypeDescriptors) {
1083 SuffixStrs.push_back((*T)->getShortStr());
1085 return join(SuffixStrs,
"_");
1090 bool HasMaskedOffOperand,
bool HasVL,
unsigned NF,
1097 if (HasMaskedOffOperand && !PolicyAttrs.isTAMAPolicy()) {
1099 NewPrototype.insert(NewPrototype.begin() + 1, NewPrototype[0]);
1100 }
else if (NF > 1) {
1106 NewPrototype.insert(NewPrototype.begin() + 1, MaskoffType);
1114 NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1118 if (HasMaskedOffOperand && NF > 1) {
1125 NewPrototype.insert(NewPrototype.begin() + 1,
1128 NewPrototype.insert(NewPrototype.begin() + NF + 1,
1136 if (PolicyAttrs.isTUPolicy() && HasPassthruOp)
1137 NewPrototype.insert(NewPrototype.begin(), NewPrototype[0]);
1138 }
else if (PolicyAttrs.isTUPolicy() && HasPassthruOp) {
1144 NewPrototype.insert(NewPrototype.begin(), MaskoffType);
1153 NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1162 return NewPrototype;
1171 bool HasMaskPolicy) {
1172 if (HasTailPolicy && HasMaskPolicy)
1179 if (HasTailPolicy && !HasMaskPolicy)
1182 if (!HasTailPolicy && HasMaskPolicy)
1185 llvm_unreachable(
"An RVV instruction should not be without both tail policy "
1191 std::string &BuiltinName,
1192 std::string &OverloadedName,
1194 bool HasFRMRoundModeOp,
bool AltFmt) {
1196 auto appendPolicySuffix = [&](
const std::string &suffix) {
1198 BuiltinName += suffix;
1199 OverloadedName += suffix;
1202 if (HasFRMRoundModeOp) {
1204 BuiltinName +=
"_rm";
1208 BuiltinName +=
"_alt";
1211 if (PolicyAttrs.isTUMUPolicy())
1212 appendPolicySuffix(
"_tumu");
1213 else if (PolicyAttrs.isTUMAPolicy())
1214 appendPolicySuffix(
"_tum");
1215 else if (PolicyAttrs.isTAMUPolicy())
1216 appendPolicySuffix(
"_mu");
1217 else if (PolicyAttrs.isTAMAPolicy()) {
1219 BuiltinName +=
"_m";
1221 llvm_unreachable(
"Unhandled policy condition");
1223 if (PolicyAttrs.isTUPolicy())
1224 appendPolicySuffix(
"_tu");
1225 else if (PolicyAttrs.isTAPolicy())
1228 llvm_unreachable(
"Unhandled policy condition");
1234 const StringRef Primaries(
"evwdqom0ztulf");
1235 while (!Prototypes.empty()) {
1239 if (Prototypes[0] ==
'(')
1240 Idx = Prototypes.find_first_of(
')');
1241 Idx = Prototypes.find_first_of(Primaries, Idx);
1242 assert(Idx != StringRef::npos);
1244 Prototypes.slice(0, Idx + 1));
1246 llvm_unreachable(
"Error during parsing prototype.");
1247 PrototypeDescriptors.push_back(*PD);
1248 Prototypes = Prototypes.drop_front(Idx + 1);
1250 return PrototypeDescriptors;
1253#define STRINGIFY(NAME) \
1271 OS <<
"/*Name=*/\"" <<
Record.Name <<
"\", ";
1272 if (
Record.OverloadedName ==
nullptr ||
1273 StringRef(
Record.OverloadedName).empty())
1274 OS <<
"/*OverloadedName=*/nullptr, ";
1276 OS <<
"/*OverloadedName=*/\"" <<
Record.OverloadedName <<
"\", ";
1277 OS <<
"/*RequiredExtensions=*/\"" <<
Record.RequiredExtensions <<
"\", ";
1278 OS <<
"/*PrototypeIndex=*/" <<
Record.PrototypeIndex <<
", ";
1279 OS <<
"/*SuffixIndex=*/" <<
Record.SuffixIndex <<
", ";
1280 OS <<
"/*OverloadedSuffixIndex=*/" <<
Record.OverloadedSuffixIndex <<
", ";
1281 OS <<
"/*PrototypeLength=*/" << (int)
Record.PrototypeLength <<
", ";
1282 OS <<
"/*SuffixLength=*/" << (int)
Record.SuffixLength <<
", ";
1283 OS <<
"/*OverloadedSuffixSize=*/" << (int)
Record.OverloadedSuffixSize <<
", ";
1284 OS <<
"/*TypeRangeMask=*/" << (int)
Record.TypeRangeMask <<
", ";
1285 OS <<
"/*Log2LMULMask=*/" << (int)
Record.Log2LMULMask <<
", ";
1286 OS <<
"/*NF=*/" << (int)
Record.NF <<
", ";
1287 OS <<
"/*HasMasked=*/" << (int)
Record.HasMasked <<
", ";
1288 OS <<
"/*HasVL=*/" << (int)
Record.HasVL <<
", ";
1289 OS <<
"/*HasMaskedOffOperand=*/" << (int)
Record.HasMaskedOffOperand <<
", ";
1290 OS <<
"/*HasTailPolicy=*/" << (int)
Record.HasTailPolicy <<
", ";
1291 OS <<
"/*HasMaskPolicy=*/" << (int)
Record.HasMaskPolicy <<
", ";
1292 OS <<
"/*HasFRMRoundModeOp=*/" << (int)
Record.HasFRMRoundModeOp <<
", ";
1293 OS <<
"/*AltFmt=*/" << (int)
Record.AltFmt <<
",";
1294 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