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!");
206 llvm_unreachable(
"ScalarType is invalid!");
209 BuiltinStr =
"I" + BuiltinStr;
217 BuiltinStr =
"q" + utostr(*Scale) + BuiltinStr;
225 BuiltinStr =
"T" + utostr(NF) + BuiltinStr;
228void RVVType::initClangBuiltinStr() {
229 assert(
isValid() &&
"RVVType is invalid");
230 assert(
isVector() &&
"Handle Vector type only");
232 ClangBuiltinStr =
"__rvv_";
233 switch (ScalarType) {
235 ClangBuiltinStr +=
"bool" + utostr(64 / *Scale) +
"_t";
238 ClangBuiltinStr +=
"float";
241 ClangBuiltinStr +=
"bfloat";
244 ClangBuiltinStr +=
"int";
247 ClangBuiltinStr +=
"uint";
250 llvm_unreachable(
"ScalarTypeKind is invalid");
252 ClangBuiltinStr += utostr(ElementBitwidth) + LMUL.str() +
253 (IsTuple ?
"x" + utostr(NF) :
"") +
"_t";
256void RVVType::initTypeStr() {
257 assert(
isValid() &&
"RVVType is invalid");
264 return Twine(TypeStr + Twine(ElementBitwidth) +
"_t").str();
265 return Twine(
"v" + TypeStr + Twine(ElementBitwidth) + LMUL.str() +
266 (IsTuple ?
"x" + utostr(NF) :
"") +
"_t")
270 switch (ScalarType) {
283 Str =
"unsigned long";
294 Str +=
"vbool" + utostr(64 / *Scale) +
"_t";
298 if (ElementBitwidth == 64)
300 else if (ElementBitwidth == 32)
302 else if (ElementBitwidth == 16)
305 llvm_unreachable(
"Unhandled floating type.");
311 if (ElementBitwidth == 16)
314 llvm_unreachable(
"Unhandled floating type.");
325 llvm_unreachable(
"ScalarType is invalid!");
331void RVVType::initShortStr() {
332 switch (ScalarType) {
335 ShortStr =
"b" + utostr(64 / *Scale);
338 ShortStr =
"f" + utostr(ElementBitwidth);
341 ShortStr =
"bf" + utostr(ElementBitwidth);
344 ShortStr =
"i" + utostr(ElementBitwidth);
347 ShortStr =
"u" + utostr(ElementBitwidth);
350 llvm_unreachable(
"Unhandled case!");
353 ShortStr += LMUL.str();
355 ShortStr +=
"x" + utostr(NF);
359 assert(2 <= NF && NF <= 8 &&
"2 <= NF <= 8");
364void RVVType::applyBasicType() {
371 ElementBitwidth = 16;
375 ElementBitwidth = 32;
379 ElementBitwidth = 64;
383 ElementBitwidth = 16;
387 ElementBitwidth = 32;
391 ElementBitwidth = 64;
395 ElementBitwidth = 16;
399 llvm_unreachable(
"Unhandled type code!");
401 assert(ElementBitwidth != 0 &&
"Bad element bitwidth!");
404std::optional<PrototypeDescriptor>
406 llvm::StringRef PrototypeDescriptorStr) {
411 if (PrototypeDescriptorStr.empty())
415 auto PType = PrototypeDescriptorStr.back();
458 llvm_unreachable(
"Illegal primitive type transformers!");
460 PD.
PT =
static_cast<uint8_t
>(
PT);
461 PrototypeDescriptorStr = PrototypeDescriptorStr.drop_back();
464 if (PrototypeDescriptorStr.starts_with(
"(")) {
466 "VectorTypeModifier should only have one modifier");
467 size_t Idx = PrototypeDescriptorStr.find(
')');
468 assert(Idx != StringRef::npos);
469 StringRef
ComplexType = PrototypeDescriptorStr.slice(1, Idx);
470 PrototypeDescriptorStr = PrototypeDescriptorStr.drop_front(Idx + 1);
471 assert(!PrototypeDescriptorStr.contains(
'(') &&
472 "Only allow one vector type modifier");
475 if (ComplexTT.first ==
"Log2EEW") {
477 if (ComplexTT.second.getAsInteger(10, Log2EEW)) {
478 llvm_unreachable(
"Invalid Log2EEW value!");
495 llvm_unreachable(
"Invalid Log2EEW value, should be [3-6]");
498 }
else if (ComplexTT.first ==
"FixedSEW") {
500 if (ComplexTT.second.getAsInteger(10, NewSEW)) {
501 llvm_unreachable(
"Invalid FixedSEW value!");
518 llvm_unreachable(
"Invalid FixedSEW value, should be 8, 16, 32 or 64");
521 }
else if (ComplexTT.first ==
"LFixedLog2LMUL") {
523 if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
524 llvm_unreachable(
"Invalid LFixedLog2LMUL value!");
550 llvm_unreachable(
"Invalid LFixedLog2LMUL value, should be [-3, 3]");
553 }
else if (ComplexTT.first ==
"SFixedLog2LMUL") {
555 if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
556 llvm_unreachable(
"Invalid SFixedLog2LMUL value!");
582 llvm_unreachable(
"Invalid LFixedLog2LMUL value, should be [-3, 3]");
586 }
else if (ComplexTT.first ==
"SEFixedLog2LMUL") {
588 if (ComplexTT.second.getAsInteger(10, Log2LMUL)) {
589 llvm_unreachable(
"Invalid SEFixedLog2LMUL value!");
615 llvm_unreachable(
"Invalid LFixedLog2LMUL value, should be [-3, 3]");
618 }
else if (ComplexTT.first ==
"Tuple") {
620 if (ComplexTT.second.getAsInteger(10, NF)) {
621 llvm_unreachable(
"Invalid NF value!");
626 llvm_unreachable(
"Illegal complex type transformers!");
629 PD.
VTM =
static_cast<uint8_t
>(
VTM);
633 for (
char I : PrototypeDescriptorStr) {
637 llvm_unreachable(
"'P' transformer cannot be used after 'C'");
639 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);
714 ElementBitwidth *= 4;
716 Scale = LMUL.
getScale(ElementBitwidth);
719 ElementBitwidth *= 8;
721 Scale = LMUL.
getScale(ElementBitwidth);
725 Scale = LMUL.
getScale(ElementBitwidth);
753 applyFixedLog2LMUL(-3, FixedLMULType::LargerThan);
756 applyFixedLog2LMUL(-2, FixedLMULType::LargerThan);
759 applyFixedLog2LMUL(-1, FixedLMULType::LargerThan);
762 applyFixedLog2LMUL(0, FixedLMULType::LargerThan);
765 applyFixedLog2LMUL(1, FixedLMULType::LargerThan);
768 applyFixedLog2LMUL(2, FixedLMULType::LargerThan);
771 applyFixedLog2LMUL(3, FixedLMULType::LargerThan);
774 applyFixedLog2LMUL(-3, FixedLMULType::SmallerThan);
777 applyFixedLog2LMUL(-2, FixedLMULType::SmallerThan);
780 applyFixedLog2LMUL(-1, FixedLMULType::SmallerThan);
783 applyFixedLog2LMUL(0, FixedLMULType::SmallerThan);
786 applyFixedLog2LMUL(1, FixedLMULType::SmallerThan);
789 applyFixedLog2LMUL(2, FixedLMULType::SmallerThan);
792 applyFixedLog2LMUL(3, FixedLMULType::SmallerThan);
795 applyFixedLog2LMUL(-3, FixedLMULType::SmallerOrEqual);
798 applyFixedLog2LMUL(-2, FixedLMULType::SmallerOrEqual);
801 applyFixedLog2LMUL(-1, FixedLMULType::SmallerOrEqual);
804 applyFixedLog2LMUL(0, FixedLMULType::SmallerOrEqual);
807 applyFixedLog2LMUL(1, FixedLMULType::SmallerOrEqual);
810 applyFixedLog2LMUL(2, FixedLMULType::SmallerOrEqual);
813 applyFixedLog2LMUL(3, FixedLMULType::SmallerOrEqual);
823 NF = 2 +
static_cast<uint8_t
>(Transformer.
VTM) -
835 for (
unsigned TypeModifierMaskShift = 0;
837 ++TypeModifierMaskShift) {
838 unsigned TypeModifierMask = 1 << TypeModifierMaskShift;
839 if ((
static_cast<unsigned>(Transformer.
TM) & TypeModifierMask) !=
868 Scale = LMUL.getScale(ElementBitwidth);
871 llvm_unreachable(
"Unknown type modifier mask!");
876void RVVType::applyLog2EEW(
unsigned Log2EEW) {
878 LMUL.MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth));
880 ElementBitwidth = 1 << Log2EEW;
882 Scale = LMUL.getScale(ElementBitwidth);
885void RVVType::applyFixedSEW(
unsigned NewSEW) {
887 if (ElementBitwidth == NewSEW) {
892 ElementBitwidth = NewSEW;
893 Scale = LMUL.getScale(ElementBitwidth);
896void RVVType::applyFixedLog2LMUL(
int Log2LMUL,
enum FixedLMULType
Type) {
898 case FixedLMULType::LargerThan:
899 if (Log2LMUL <= LMUL.Log2LMUL) {
904 case FixedLMULType::SmallerThan:
905 if (Log2LMUL >= LMUL.Log2LMUL) {
910 case FixedLMULType::SmallerOrEqual:
911 if (Log2LMUL > LMUL.Log2LMUL) {
919 LMUL = LMULType(Log2LMUL);
920 Scale = LMUL.getScale(ElementBitwidth);
923std::optional<RVVTypes>
943 assert(Log2LMUL >= -3 && Log2LMUL <= 3);
944 return (Log2LMUL + 3) | (
static_cast<uint64_t
>(BT) & 0xff) << 8 |
945 ((uint64_t)(Proto.
PT & 0xff) << 16) |
946 ((uint64_t)(Proto.
TM & 0xff) << 24) |
947 ((uint64_t)(Proto.
VTM & 0xff) << 32);
954 auto It = LegalTypes.find(Idx);
955 if (It != LegalTypes.end())
956 return &(It->second);
958 if (IllegalTypes.count(Idx))
965 std::pair<std::unordered_map<uint64_t, RVVType>::iterator,
bool>
966 InsertResult = LegalTypes.insert({Idx,
T});
967 return &(InsertResult.first->second);
970 IllegalTypes.insert(Idx);
978 StringRef NewName, StringRef Suffix, StringRef NewOverloadedName,
979 StringRef OverloadedSuffix, StringRef IRName,
bool IsMasked,
980 bool HasMaskedOffOperand,
bool HasVL,
PolicyScheme Scheme,
981 bool SupportOverloading,
bool HasBuiltinAlias, StringRef ManualCodegen,
982 const RVVTypes &OutInTypes,
const std::vector<int64_t> &NewIntrinsicTypes,
983 unsigned NF,
Policy NewPolicyAttrs,
bool HasFRMRoundModeOp,
unsigned TWiden)
984 : IRName(IRName), IsMasked(IsMasked),
985 HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme),
986 SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias),
987 ManualCodegen(ManualCodegen.str()), NF(NF), PolicyAttrs(NewPolicyAttrs),
991 BuiltinName = NewName.str();
993 if (NewOverloadedName.empty())
994 OverloadedName = NewName.split(
"_").first.str();
996 OverloadedName = NewOverloadedName.str();
998 Name +=
"_" + Suffix.str();
999 if (!OverloadedSuffix.empty())
1000 OverloadedName +=
"_" + OverloadedSuffix.str();
1003 PolicyAttrs, HasFRMRoundModeOp);
1006 OutputType = OutInTypes[0];
1007 InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
1011 IntrinsicTypes = NewIntrinsicTypes;
1014 for (
auto &I : IntrinsicTypes) {
1023 S += OutputType->getBuiltinStr();
1024 for (
const auto &
T : InputTypes) {
1025 S +=
T->getBuiltinStr();
1034 for (
auto PD : PrototypeDescriptors) {
1036 SuffixStrs.push_back((*T)->getShortStr());
1038 return join(SuffixStrs,
"_");
1043 bool HasMaskedOffOperand,
bool HasVL,
unsigned NF,
1050 if (HasMaskedOffOperand && !PolicyAttrs.isTAMAPolicy()) {
1052 NewPrototype.insert(NewPrototype.begin() + 1, NewPrototype[0]);
1053 }
else if (NF > 1) {
1060 NewPrototype.insert(NewPrototype.begin() + 1, MaskoffType);
1068 NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1072 if (HasMaskedOffOperand && NF > 1) {
1079 NewPrototype.insert(NewPrototype.begin() + 1,
1082 NewPrototype.insert(NewPrototype.begin() + NF + 1,
1090 if (PolicyAttrs.isTUPolicy() && HasPassthruOp)
1091 NewPrototype.insert(NewPrototype.begin(), NewPrototype[0]);
1092 }
else if (PolicyAttrs.isTUPolicy() && HasPassthruOp) {
1099 NewPrototype.insert(NewPrototype.begin(), MaskoffType);
1108 NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1117 return NewPrototype;
1126 bool HasMaskPolicy) {
1127 if (HasTailPolicy && HasMaskPolicy)
1134 if (HasTailPolicy && !HasMaskPolicy)
1137 if (!HasTailPolicy && HasMaskPolicy)
1140 llvm_unreachable(
"An RVV instruction should not be without both tail policy "
1145 bool IsMasked,
bool HasPolicy, std::string &Name, std::string &BuiltinName,
1146 std::string &OverloadedName,
Policy &PolicyAttrs,
bool HasFRMRoundModeOp) {
1148 auto appendPolicySuffix = [&](
const std::string &suffix) {
1150 BuiltinName += suffix;
1151 OverloadedName += suffix;
1154 if (HasFRMRoundModeOp) {
1156 BuiltinName +=
"_rm";
1160 if (PolicyAttrs.isTUMUPolicy())
1161 appendPolicySuffix(
"_tumu");
1162 else if (PolicyAttrs.isTUMAPolicy())
1163 appendPolicySuffix(
"_tum");
1164 else if (PolicyAttrs.isTAMUPolicy())
1165 appendPolicySuffix(
"_mu");
1166 else if (PolicyAttrs.isTAMAPolicy()) {
1168 BuiltinName +=
"_m";
1170 llvm_unreachable(
"Unhandled policy condition");
1172 if (PolicyAttrs.isTUPolicy())
1173 appendPolicySuffix(
"_tu");
1174 else if (PolicyAttrs.isTAPolicy())
1177 llvm_unreachable(
"Unhandled policy condition");
1183 const StringRef Primaries(
"evwqom0ztulf");
1184 while (!Prototypes.empty()) {
1188 if (Prototypes[0] ==
'(')
1189 Idx = Prototypes.find_first_of(
')');
1190 Idx = Prototypes.find_first_of(Primaries, Idx);
1191 assert(Idx != StringRef::npos);
1193 Prototypes.slice(0, Idx + 1));
1195 llvm_unreachable(
"Error during parsing prototype.");
1196 PrototypeDescriptors.push_back(*PD);
1197 Prototypes = Prototypes.drop_front(Idx + 1);
1199 return PrototypeDescriptors;
1202#define STRINGIFY(NAME) \
1220 OS <<
"/*Name=*/\"" <<
Record.Name <<
"\", ";
1221 if (
Record.OverloadedName ==
nullptr ||
1222 StringRef(
Record.OverloadedName).empty())
1223 OS <<
"/*OverloadedName=*/nullptr, ";
1225 OS <<
"/*OverloadedName=*/\"" <<
Record.OverloadedName <<
"\", ";
1226 OS <<
"/*RequiredExtensions=*/\"" <<
Record.RequiredExtensions <<
"\", ";
1227 OS <<
"/*PrototypeIndex=*/" <<
Record.PrototypeIndex <<
", ";
1228 OS <<
"/*SuffixIndex=*/" <<
Record.SuffixIndex <<
", ";
1229 OS <<
"/*OverloadedSuffixIndex=*/" <<
Record.OverloadedSuffixIndex <<
", ";
1230 OS <<
"/*PrototypeLength=*/" << (int)
Record.PrototypeLength <<
", ";
1231 OS <<
"/*SuffixLength=*/" << (int)
Record.SuffixLength <<
", ";
1232 OS <<
"/*OverloadedSuffixSize=*/" << (int)
Record.OverloadedSuffixSize <<
", ";
1233 OS <<
"/*TypeRangeMask=*/" << (int)
Record.TypeRangeMask <<
", ";
1234 OS <<
"/*Log2LMULMask=*/" << (int)
Record.Log2LMULMask <<
", ";
1235 OS <<
"/*NF=*/" << (int)
Record.NF <<
", ";
1236 OS <<
"/*HasMasked=*/" << (int)
Record.HasMasked <<
", ";
1237 OS <<
"/*HasVL=*/" << (int)
Record.HasVL <<
", ";
1238 OS <<
"/*HasMaskedOffOperand=*/" << (int)
Record.HasMaskedOffOperand <<
", ";
1239 OS <<
"/*HasTailPolicy=*/" << (int)
Record.HasTailPolicy <<
", ";
1240 OS <<
"/*HasMaskPolicy=*/" << (int)
Record.HasMaskPolicy <<
", ";
1241 OS <<
"/*HasFRMRoundModeOp=*/" << (int)
Record.HasFRMRoundModeOp <<
", ";
1242 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)
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 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)
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