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");
661 llvm_unreachable(
"Illegal non-primitive type transformer!");
664 PD.
TM =
static_cast<uint8_t
>(
TM);
676 Scale = LMUL.
getScale(ElementBitwidth);
694 ElementBitwidth = 32;
704 ElementBitwidth *= 2;
706 Scale = LMUL.
getScale(ElementBitwidth);
709 ElementBitwidth *= 4;
711 Scale = LMUL.
getScale(ElementBitwidth);
714 ElementBitwidth *= 8;
716 Scale = LMUL.
getScale(ElementBitwidth);
720 Scale = LMUL.
getScale(ElementBitwidth);
748 applyFixedLog2LMUL(-3, FixedLMULType::LargerThan);
751 applyFixedLog2LMUL(-2, FixedLMULType::LargerThan);
754 applyFixedLog2LMUL(-1, FixedLMULType::LargerThan);
757 applyFixedLog2LMUL(0, FixedLMULType::LargerThan);
760 applyFixedLog2LMUL(1, FixedLMULType::LargerThan);
763 applyFixedLog2LMUL(2, FixedLMULType::LargerThan);
766 applyFixedLog2LMUL(3, FixedLMULType::LargerThan);
769 applyFixedLog2LMUL(-3, FixedLMULType::SmallerThan);
772 applyFixedLog2LMUL(-2, FixedLMULType::SmallerThan);
775 applyFixedLog2LMUL(-1, FixedLMULType::SmallerThan);
778 applyFixedLog2LMUL(0, FixedLMULType::SmallerThan);
781 applyFixedLog2LMUL(1, FixedLMULType::SmallerThan);
784 applyFixedLog2LMUL(2, FixedLMULType::SmallerThan);
787 applyFixedLog2LMUL(3, FixedLMULType::SmallerThan);
790 applyFixedLog2LMUL(-3, FixedLMULType::SmallerOrEqual);
793 applyFixedLog2LMUL(-2, FixedLMULType::SmallerOrEqual);
796 applyFixedLog2LMUL(-1, FixedLMULType::SmallerOrEqual);
799 applyFixedLog2LMUL(0, FixedLMULType::SmallerOrEqual);
802 applyFixedLog2LMUL(1, FixedLMULType::SmallerOrEqual);
805 applyFixedLog2LMUL(2, FixedLMULType::SmallerOrEqual);
808 applyFixedLog2LMUL(3, FixedLMULType::SmallerOrEqual);
818 NF = 2 +
static_cast<uint8_t
>(Transformer.
VTM) -
830 for (
unsigned TypeModifierMaskShift = 0;
832 ++TypeModifierMaskShift) {
833 unsigned TypeModifierMask = 1 << TypeModifierMaskShift;
834 if ((
static_cast<unsigned>(Transformer.
TM) & TypeModifierMask) !=
863 Scale = LMUL.
getScale(ElementBitwidth);
866 llvm_unreachable(
"Unknown type modifier mask!");
871void RVVType::applyLog2EEW(
unsigned Log2EEW) {
873 LMUL.
MulLog2LMUL(Log2EEW - Log2_32(ElementBitwidth));
875 ElementBitwidth = 1 << Log2EEW;
877 Scale = LMUL.
getScale(ElementBitwidth);
880void RVVType::applyFixedSEW(
unsigned NewSEW) {
882 if (ElementBitwidth == NewSEW) {
887 ElementBitwidth = NewSEW;
888 Scale = LMUL.
getScale(ElementBitwidth);
891void RVVType::applyFixedLog2LMUL(
int Log2LMUL,
enum FixedLMULType Type) {
893 case FixedLMULType::LargerThan:
899 case FixedLMULType::SmallerThan:
905 case FixedLMULType::SmallerOrEqual:
914 LMUL = LMULType(Log2LMUL);
915 Scale = LMUL.
getScale(ElementBitwidth);
918std::optional<RVVTypes>
938 assert(Log2LMUL >= -3 && Log2LMUL <= 3);
939 return (Log2LMUL + 3) | (
static_cast<uint64_t
>(BT) & 0xff) << 8 |
940 ((uint64_t)(Proto.
PT & 0xff) << 16) |
941 ((uint64_t)(Proto.
TM & 0xff) << 24) |
942 ((uint64_t)(Proto.
VTM & 0xff) << 32);
949 auto It = LegalTypes.find(Idx);
950 if (It != LegalTypes.end())
951 return &(It->second);
953 if (IllegalTypes.count(Idx))
960 std::pair<std::unordered_map<uint64_t, RVVType>::iterator,
bool>
961 InsertResult = LegalTypes.insert({Idx,
T});
962 return &(InsertResult.first->second);
965 IllegalTypes.insert(Idx);
973 StringRef NewName, StringRef Suffix, StringRef NewOverloadedName,
974 StringRef OverloadedSuffix, StringRef IRName,
bool IsMasked,
975 bool HasMaskedOffOperand,
bool HasVL,
PolicyScheme Scheme,
976 bool SupportOverloading,
bool HasBuiltinAlias, StringRef ManualCodegen,
977 const RVVTypes &OutInTypes,
const std::vector<int64_t> &NewIntrinsicTypes,
978 unsigned NF,
Policy NewPolicyAttrs,
bool HasFRMRoundModeOp)
979 : IRName(IRName), IsMasked(IsMasked),
980 HasMaskedOffOperand(HasMaskedOffOperand), HasVL(HasVL), Scheme(Scheme),
981 SupportOverloading(SupportOverloading), HasBuiltinAlias(HasBuiltinAlias),
982 ManualCodegen(ManualCodegen.str()), NF(NF), PolicyAttrs(NewPolicyAttrs) {
985 BuiltinName = NewName.str();
987 if (NewOverloadedName.empty())
988 OverloadedName = NewName.split(
"_").first.str();
990 OverloadedName = NewOverloadedName.str();
992 Name +=
"_" + Suffix.str();
993 if (!OverloadedSuffix.empty())
994 OverloadedName +=
"_" + OverloadedSuffix.str();
997 PolicyAttrs, HasFRMRoundModeOp);
1000 OutputType = OutInTypes[0];
1001 InputTypes.assign(OutInTypes.begin() + 1, OutInTypes.end());
1005 IntrinsicTypes = NewIntrinsicTypes;
1008 for (
auto &I : IntrinsicTypes) {
1018 for (
const auto &
T : InputTypes) {
1019 S +=
T->getBuiltinStr();
1028 for (
auto PD : PrototypeDescriptors) {
1030 SuffixStrs.push_back((*T)->getShortStr());
1032 return join(SuffixStrs,
"_");
1037 bool HasMaskedOffOperand,
bool HasVL,
unsigned NF,
1044 if (HasMaskedOffOperand && !PolicyAttrs.
isTAMAPolicy()) {
1046 NewPrototype.insert(NewPrototype.begin() + 1, NewPrototype[0]);
1047 }
else if (NF > 1) {
1054 NewPrototype.insert(NewPrototype.begin() + 1, MaskoffType);
1062 NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1066 if (HasMaskedOffOperand && NF > 1) {
1073 NewPrototype.insert(NewPrototype.begin() + 1,
1076 NewPrototype.insert(NewPrototype.begin() + NF + 1,
1084 if (PolicyAttrs.
isTUPolicy() && HasPassthruOp)
1085 NewPrototype.insert(NewPrototype.begin(), NewPrototype[0]);
1086 }
else if (PolicyAttrs.
isTUPolicy() && HasPassthruOp) {
1093 NewPrototype.insert(NewPrototype.begin(), MaskoffType);
1102 NewPrototype.insert(NewPrototype.begin() + NF + 1, NF, MaskoffType);
1111 return NewPrototype;
1120 bool HasMaskPolicy) {
1121 if (HasTailPolicy && HasMaskPolicy)
1128 if (HasTailPolicy && !HasMaskPolicy)
1131 if (!HasTailPolicy && HasMaskPolicy)
1134 llvm_unreachable(
"An RVV instruction should not be without both tail policy "
1139 bool IsMasked,
bool HasPolicy, std::string &Name, std::string &BuiltinName,
1140 std::string &OverloadedName,
Policy &PolicyAttrs,
bool HasFRMRoundModeOp) {
1142 auto appendPolicySuffix = [&](
const std::string &suffix) {
1144 BuiltinName += suffix;
1145 OverloadedName += suffix;
1148 if (HasFRMRoundModeOp) {
1150 BuiltinName +=
"_rm";
1155 appendPolicySuffix(
"_tumu");
1157 appendPolicySuffix(
"_tum");
1159 appendPolicySuffix(
"_mu");
1162 BuiltinName +=
"_m";
1164 llvm_unreachable(
"Unhandled policy condition");
1167 appendPolicySuffix(
"_tu");
1171 llvm_unreachable(
"Unhandled policy condition");
1177 const StringRef Primaries(
"evwqom0ztulf");
1178 while (!Prototypes.empty()) {
1182 if (Prototypes[0] ==
'(')
1183 Idx = Prototypes.find_first_of(
')');
1184 Idx = Prototypes.find_first_of(Primaries, Idx);
1185 assert(Idx != StringRef::npos);
1187 Prototypes.slice(0, Idx + 1));
1189 llvm_unreachable(
"Error during parsing prototype.");
1190 PrototypeDescriptors.push_back(*PD);
1191 Prototypes = Prototypes.drop_front(Idx + 1);
1193 return PrototypeDescriptors;
1196#define STRINGIFY(NAME) \
1214 OS <<
"/*Name=*/\"" <<
Record.Name <<
"\", ";
1215 if (
Record.OverloadedName ==
nullptr ||
1216 StringRef(
Record.OverloadedName).empty())
1217 OS <<
"/*OverloadedName=*/nullptr, ";
1219 OS <<
"/*OverloadedName=*/\"" <<
Record.OverloadedName <<
"\", ";
1220 OS <<
"/*RequiredExtensions=*/\"" <<
Record.RequiredExtensions <<
"\", ";
1221 OS <<
"/*PrototypeIndex=*/" <<
Record.PrototypeIndex <<
", ";
1222 OS <<
"/*SuffixIndex=*/" <<
Record.SuffixIndex <<
", ";
1223 OS <<
"/*OverloadedSuffixIndex=*/" <<
Record.OverloadedSuffixIndex <<
", ";
1224 OS <<
"/*PrototypeLength=*/" << (
int)
Record.PrototypeLength <<
", ";
1225 OS <<
"/*SuffixLength=*/" << (
int)
Record.SuffixLength <<
", ";
1226 OS <<
"/*OverloadedSuffixSize=*/" << (
int)
Record.OverloadedSuffixSize <<
", ";
1227 OS <<
"/*TypeRangeMask=*/" << (
int)
Record.TypeRangeMask <<
", ";
1228 OS <<
"/*Log2LMULMask=*/" << (
int)
Record.Log2LMULMask <<
", ";
1229 OS <<
"/*NF=*/" << (
int)
Record.NF <<
", ";
1230 OS <<
"/*HasMasked=*/" << (
int)
Record.HasMasked <<
", ";
1231 OS <<
"/*HasVL=*/" << (
int)
Record.HasVL <<
", ";
1232 OS <<
"/*HasMaskedOffOperand=*/" << (
int)
Record.HasMaskedOffOperand <<
", ";
1233 OS <<
"/*HasTailPolicy=*/" << (
int)
Record.HasTailPolicy <<
", ";
1234 OS <<
"/*HasMaskPolicy=*/" << (
int)
Record.HasMaskPolicy <<
", ";
1235 OS <<
"/*HasFRMRoundModeOp=*/" << (
int)
Record.HasFRMRoundModeOp <<
", ";
1236 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 isTUMUPolicy() const
bool isTUMAPolicy() const
bool isTAMUPolicy() const
bool isTAMAPolicy() const
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 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)
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)
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
const std::string & getBuiltinStr() const
The base class of the type hierarchy.
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, enum PolicyScheme PS)
llvm::SmallVector< PrototypeDescriptor > parsePrototypes(llvm::StringRef Prototypes)
static uint64_t computeRVVTypeHashValue(BasicType BT, int Log2LMUL, PrototypeDescriptor Proto)
std::optional< unsigned > VScaleVal
static VectorTypeModifier getTupleVTM(unsigned NF)
std::vector< RVVTypePtr > RVVTypes
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
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
static const PrototypeDescriptor Mask
static const PrototypeDescriptor Vector