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();
482 llvm_unreachable(
"Illegal primitive type transformers!");
484 PD.
PT =
static_cast<uint8_t
>(
PT);
485 PrototypeDescriptorStr = PrototypeDescriptorStr.drop_back();
488 if (PrototypeDescriptorStr.starts_with(
"(")) {
490 "VectorTypeModifier should only have one modifier");
491 size_t Idx = PrototypeDescriptorStr.find(
')');
492 assert(Idx != StringRef::npos);
493 StringRef
ComplexType = PrototypeDescriptorStr.slice(1, Idx);
494 PrototypeDescriptorStr = PrototypeDescriptorStr.drop_front(Idx + 1);
495 assert(!PrototypeDescriptorStr.contains(
'(') &&
496 "Only allow one vector type modifier");
499 if (ComplexTT.first ==
"Log2EEW") {
501 if (ComplexTT.second.getAsInteger(10, Log2EEW)) {
502 llvm_unreachable(
"Invalid Log2EEW value!");
519 llvm_unreachable(
"Invalid Log2EEW value, should be [3-6]");
522 }
else if (ComplexTT.first ==
"FixedSEW") {
524 if (ComplexTT.second.getAsInteger(10, NewSEW)) {
525 llvm_unreachable(
"Invalid FixedSEW value!");
542 llvm_unreachable(
"Invalid FixedSEW value, should be 8, 16, 32 or 64");
545 }
else if (ComplexTT.first ==
"LFixedLog2LMUL") {
547 if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
548 llvm_unreachable(
"Invalid LFixedLog2LMUL value!");
574 llvm_unreachable(
"Invalid LFixedLog2LMUL value, should be [-3, 3]");
577 }
else if (ComplexTT.first ==
"SFixedLog2LMUL") {
579 if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
580 llvm_unreachable(
"Invalid SFixedLog2LMUL value!");
606 llvm_unreachable(
"Invalid LFixedLog2LMUL value, should be [-3, 3]");
610 }
else if (ComplexTT.first ==
"SEFixedLog2LMUL") {
612 if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
613 llvm_unreachable(
"Invalid SEFixedLog2LMUL value!");
639 llvm_unreachable(
"Invalid LFixedLog2LMUL value, should be [-3, 3]");
642 }
else if (ComplexTT.first ==
"Tuple") {
644 if (ComplexTT.second.getAsInteger(10, NF)) {
645 llvm_unreachable(
"Invalid NF value!");
650 llvm_unreachable(
"Illegal complex type transformers!");
653 PD.
VTM =
static_cast<uint8_t
>(
VTM);
657 for (
char I : PrototypeDescriptorStr) {
661 llvm_unreachable(
"'P' transformer cannot be used after 'C'");
663 llvm_unreachable(
"'P' transformer cannot be used twice");
688 llvm_unreachable(
"Illegal non-primitive type transformer!");
691 PD.
TM =
static_cast<uint8_t
>(
TM);
703 Scale = LMUL.
getScale(ElementBitwidth);
721 ElementBitwidth = 32;
731 ElementBitwidth *= 2;
733 Scale = LMUL.
getScale(ElementBitwidth);
741 ElementBitwidth *= 4;
743 Scale = LMUL.
getScale(ElementBitwidth);
749 ElementBitwidth *= 8;
751 Scale = LMUL.
getScale(ElementBitwidth);
755 Scale = LMUL.
getScale(ElementBitwidth);
783 applyFixedLog2LMUL(-3, FixedLMULType::LargerThan);
786 applyFixedLog2LMUL(-2, FixedLMULType::LargerThan);
789 applyFixedLog2LMUL(-1, FixedLMULType::LargerThan);
792 applyFixedLog2LMUL(0, FixedLMULType::LargerThan);
795 applyFixedLog2LMUL(1, FixedLMULType::LargerThan);
798 applyFixedLog2LMUL(2, FixedLMULType::LargerThan);
801 applyFixedLog2LMUL(3, FixedLMULType::LargerThan);
804 applyFixedLog2LMUL(-3, FixedLMULType::SmallerThan);
807 applyFixedLog2LMUL(-2, FixedLMULType::SmallerThan);
810 applyFixedLog2LMUL(-1, FixedLMULType::SmallerThan);
813 applyFixedLog2LMUL(0, FixedLMULType::SmallerThan);
816 applyFixedLog2LMUL(1, FixedLMULType::SmallerThan);
819 applyFixedLog2LMUL(2, FixedLMULType::SmallerThan);
822 applyFixedLog2LMUL(3, FixedLMULType::SmallerThan);
825 applyFixedLog2LMUL(-3, FixedLMULType::SmallerOrEqual);
828 applyFixedLog2LMUL(-2, FixedLMULType::SmallerOrEqual);
831 applyFixedLog2LMUL(-1, FixedLMULType::SmallerOrEqual);
834 applyFixedLog2LMUL(0, FixedLMULType::SmallerOrEqual);
837 applyFixedLog2LMUL(1, FixedLMULType::SmallerOrEqual);
840 applyFixedLog2LMUL(2, FixedLMULType::SmallerOrEqual);
843 applyFixedLog2LMUL(3, FixedLMULType::SmallerOrEqual);
853 NF = 2 +
static_cast<uint8_t
>(Transformer.
VTM) -
865 for (
unsigned TypeModifierMaskShift = 0;
867 ++TypeModifierMaskShift) {
868 unsigned TypeModifierMask = 1 << TypeModifierMaskShift;
869 if ((
static_cast<unsigned>(Transformer.
TM) & TypeModifierMask) !=
898 Scale = LMUL.getScale(ElementBitwidth);
901 llvm_unreachable(
"Unknown type modifier mask!");
906void RVVType::applyLog2EEW(
unsigned Log2EEW) {
908 LMUL.MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth));
910 ElementBitwidth = 1 << Log2EEW;
912 Scale = LMUL.getScale(ElementBitwidth);
915void RVVType::applyFixedSEW(
unsigned NewSEW) {
917 if (ElementBitwidth == NewSEW) {
922 ElementBitwidth = NewSEW;
923 Scale = LMUL.getScale(ElementBitwidth);
926void RVVType::applyFixedLog2LMUL(
int Log2LMUL,
enum FixedLMULType
Type) {
928 case FixedLMULType::LargerThan:
929 if (Log2LMUL <= LMUL.Log2LMUL) {
934 case FixedLMULType::SmallerThan:
935 if (Log2LMUL >= LMUL.Log2LMUL) {
940 case FixedLMULType::SmallerOrEqual:
941 if (Log2LMUL > LMUL.Log2LMUL) {
949 LMUL = LMULType(Log2LMUL);
950 Scale = LMUL.getScale(ElementBitwidth);
953std::optional<RVVTypes>
973 assert(Log2LMUL >= -3 && Log2LMUL <= 3);
974 return (Log2LMUL + 3) | (
static_cast<uint64_t
>(BT) & 0xffff) << 8 |
975 ((uint64_t)(Proto.
PT & 0xff) << 24) |
976 ((uint64_t)(Proto.
TM & 0xff) << 32) |
977 ((uint64_t)(Proto.
VTM & 0xff) << 40);
984 auto It = LegalTypes.find(Idx);
985 if (It != LegalTypes.end())
986 return &(It->second);
988 if (IllegalTypes.count(Idx))
995 std::pair<std::unordered_map<uint64_t, RVVType>::iterator,
bool>
996 InsertResult = LegalTypes.insert({Idx,
T});
997 return &(InsertResult.first->second);
1000 IllegalTypes.insert(Idx);
1001 return std::nullopt;
1008 StringRef NewOverloadedName,
1009 StringRef OverloadedSuffix, StringRef IRName,
1010 bool IsMasked,
bool HasMaskedOffOperand,
bool HasVL,
1012 bool HasBuiltinAlias, StringRef ManualCodegen,
1014 const std::vector<int64_t> &NewIntrinsicTypes,
1015 unsigned NF,
Policy NewPolicyAttrs,
1016 bool HasFRMRoundModeOp,
unsigned TWiden,
bool AltFmt)
1017 : IRName(IRName), IsMasked(IsMasked),
1018 HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme),
1019 SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias),
1020 ManualCodegen(ManualCodegen.str()), NF(NF), PolicyAttrs(NewPolicyAttrs),
1024 BuiltinName = NewName.str();
1026 if (NewOverloadedName.empty())
1027 OverloadedName = NewName.split(
"_").first.str();
1029 OverloadedName = NewOverloadedName.str();
1030 if (!Suffix.empty())
1031 Name +=
"_" + Suffix.str();
1032 if (!OverloadedSuffix.empty())
1033 OverloadedName +=
"_" + OverloadedSuffix.str();
1036 PolicyAttrs, HasFRMRoundModeOp, AltFmt);
1039 OutputType = OutInTypes[0];
1040 InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
1044 IntrinsicTypes = NewIntrinsicTypes;
1047 for (
auto &I : IntrinsicTypes) {
1056 S += OutputType->getBuiltinStr();
1057 for (
const auto &
T : InputTypes) {
1058 S +=
T->getBuiltinStr();
1067 for (
auto PD : PrototypeDescriptors) {
1069 SuffixStrs.push_back((*T)->getShortStr());
1071 return join(SuffixStrs,
"_");
1076 bool HasMaskedOffOperand,
bool HasVL,
unsigned NF,
1083 if (HasMaskedOffOperand && !PolicyAttrs.isTAMAPolicy()) {
1085 NewPrototype.insert(NewPrototype.begin() + 1, NewPrototype[0]);
1086 }
else if (NF > 1) {
1093 NewPrototype.insert(NewPrototype.begin() + 1, MaskoffType);
1101 NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1105 if (HasMaskedOffOperand && NF > 1) {
1112 NewPrototype.insert(NewPrototype.begin() + 1,
1115 NewPrototype.insert(NewPrototype.begin() + NF + 1,
1123 if (PolicyAttrs.isTUPolicy() && HasPassthruOp)
1124 NewPrototype.insert(NewPrototype.begin(), NewPrototype[0]);
1125 }
else if (PolicyAttrs.isTUPolicy() && HasPassthruOp) {
1132 NewPrototype.insert(NewPrototype.begin(), MaskoffType);
1141 NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1150 return NewPrototype;
1159 bool HasMaskPolicy) {
1160 if (HasTailPolicy && HasMaskPolicy)
1167 if (HasTailPolicy && !HasMaskPolicy)
1170 if (!HasTailPolicy && HasMaskPolicy)
1173 llvm_unreachable(
"An RVV instruction should not be without both tail policy "
1179 std::string &BuiltinName,
1180 std::string &OverloadedName,
1182 bool HasFRMRoundModeOp,
bool AltFmt) {
1184 auto appendPolicySuffix = [&](
const std::string &suffix) {
1186 BuiltinName += suffix;
1187 OverloadedName += suffix;
1190 if (HasFRMRoundModeOp) {
1192 BuiltinName +=
"_rm";
1196 BuiltinName +=
"_alt";
1199 if (PolicyAttrs.isTUMUPolicy())
1200 appendPolicySuffix(
"_tumu");
1201 else if (PolicyAttrs.isTUMAPolicy())
1202 appendPolicySuffix(
"_tum");
1203 else if (PolicyAttrs.isTAMUPolicy())
1204 appendPolicySuffix(
"_mu");
1205 else if (PolicyAttrs.isTAMAPolicy()) {
1207 BuiltinName +=
"_m";
1209 llvm_unreachable(
"Unhandled policy condition");
1211 if (PolicyAttrs.isTUPolicy())
1212 appendPolicySuffix(
"_tu");
1213 else if (PolicyAttrs.isTAPolicy())
1216 llvm_unreachable(
"Unhandled policy condition");
1222 const StringRef Primaries(
"evwqom0ztulf");
1223 while (!Prototypes.empty()) {
1227 if (Prototypes[0] ==
'(')
1228 Idx = Prototypes.find_first_of(
')');
1229 Idx = Prototypes.find_first_of(Primaries, Idx);
1230 assert(Idx != StringRef::npos);
1232 Prototypes.slice(0, Idx + 1));
1234 llvm_unreachable(
"Error during parsing prototype.");
1235 PrototypeDescriptors.push_back(*PD);
1236 Prototypes = Prototypes.drop_front(Idx + 1);
1238 return PrototypeDescriptors;
1241#define STRINGIFY(NAME) \
1259 OS <<
"/*Name=*/\"" <<
Record.Name <<
"\", ";
1260 if (
Record.OverloadedName ==
nullptr ||
1261 StringRef(
Record.OverloadedName).empty())
1262 OS <<
"/*OverloadedName=*/nullptr, ";
1264 OS <<
"/*OverloadedName=*/\"" <<
Record.OverloadedName <<
"\", ";
1265 OS <<
"/*RequiredExtensions=*/\"" <<
Record.RequiredExtensions <<
"\", ";
1266 OS <<
"/*PrototypeIndex=*/" <<
Record.PrototypeIndex <<
", ";
1267 OS <<
"/*SuffixIndex=*/" <<
Record.SuffixIndex <<
", ";
1268 OS <<
"/*OverloadedSuffixIndex=*/" <<
Record.OverloadedSuffixIndex <<
", ";
1269 OS <<
"/*PrototypeLength=*/" << (int)
Record.PrototypeLength <<
", ";
1270 OS <<
"/*SuffixLength=*/" << (int)
Record.SuffixLength <<
", ";
1271 OS <<
"/*OverloadedSuffixSize=*/" << (int)
Record.OverloadedSuffixSize <<
", ";
1272 OS <<
"/*TypeRangeMask=*/" << (int)
Record.TypeRangeMask <<
", ";
1273 OS <<
"/*Log2LMULMask=*/" << (int)
Record.Log2LMULMask <<
", ";
1274 OS <<
"/*NF=*/" << (int)
Record.NF <<
", ";
1275 OS <<
"/*HasMasked=*/" << (int)
Record.HasMasked <<
", ";
1276 OS <<
"/*HasVL=*/" << (int)
Record.HasVL <<
", ";
1277 OS <<
"/*HasMaskedOffOperand=*/" << (int)
Record.HasMaskedOffOperand <<
", ";
1278 OS <<
"/*HasTailPolicy=*/" << (int)
Record.HasTailPolicy <<
", ";
1279 OS <<
"/*HasMaskPolicy=*/" << (int)
Record.HasMaskPolicy <<
", ";
1280 OS <<
"/*HasFRMRoundModeOp=*/" << (int)
Record.HasFRMRoundModeOp <<
", ";
1281 OS <<
"/*AltFmt=*/" << (int)
Record.AltFmt <<
",";
1282 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())))
const FunctionProtoType * T
@ 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