diff options
Diffstat (limited to 'llvm/lib/Support/RISCVISAInfo.cpp')
-rw-r--r-- | llvm/lib/Support/RISCVISAInfo.cpp | 208 |
1 files changed, 185 insertions, 23 deletions
diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp index e2e4340f44e9..6c59d8a7ef04 100644 --- a/llvm/lib/Support/RISCVISAInfo.cpp +++ b/llvm/lib/Support/RISCVISAInfo.cpp @@ -9,6 +9,7 @@ #include "llvm/Support/RISCVISAInfo.h" #include "llvm/ADT/None.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Errc.h" @@ -46,25 +47,56 @@ static const RISCVSupportedExtension SupportedExtensions[] = { {"f", RISCVExtensionVersion{2, 0}}, {"d", RISCVExtensionVersion{2, 0}}, {"c", RISCVExtensionVersion{2, 0}}, -}; -static const RISCVSupportedExtension SupportedExperimentalExtensions[] = { - {"v", RISCVExtensionVersion{0, 10}}, + {"zfhmin", RISCVExtensionVersion{1, 0}}, + {"zfh", RISCVExtensionVersion{1, 0}}, + {"zba", RISCVExtensionVersion{1, 0}}, {"zbb", RISCVExtensionVersion{1, 0}}, {"zbc", RISCVExtensionVersion{1, 0}}, + {"zbs", RISCVExtensionVersion{1, 0}}, + + {"zbkb", RISCVExtensionVersion{1, 0}}, + {"zbkc", RISCVExtensionVersion{1, 0}}, + {"zbkx", RISCVExtensionVersion{1, 0}}, + {"zknd", RISCVExtensionVersion{1, 0}}, + {"zkne", RISCVExtensionVersion{1, 0}}, + {"zknh", RISCVExtensionVersion{1, 0}}, + {"zksed", RISCVExtensionVersion{1, 0}}, + {"zksh", RISCVExtensionVersion{1, 0}}, + {"zkr", RISCVExtensionVersion{1, 0}}, + {"zkn", RISCVExtensionVersion{1, 0}}, + {"zks", RISCVExtensionVersion{1, 0}}, + {"zkt", RISCVExtensionVersion{1, 0}}, + {"zk", RISCVExtensionVersion{1, 0}}, + + {"v", RISCVExtensionVersion{1, 0}}, + {"zvl32b", RISCVExtensionVersion{1, 0}}, + {"zvl64b", RISCVExtensionVersion{1, 0}}, + {"zvl128b", RISCVExtensionVersion{1, 0}}, + {"zvl256b", RISCVExtensionVersion{1, 0}}, + {"zvl512b", RISCVExtensionVersion{1, 0}}, + {"zvl1024b", RISCVExtensionVersion{1, 0}}, + {"zvl2048b", RISCVExtensionVersion{1, 0}}, + {"zvl4096b", RISCVExtensionVersion{1, 0}}, + {"zvl8192b", RISCVExtensionVersion{1, 0}}, + {"zvl16384b", RISCVExtensionVersion{1, 0}}, + {"zvl32768b", RISCVExtensionVersion{1, 0}}, + {"zvl65536b", RISCVExtensionVersion{1, 0}}, + {"zve32x", RISCVExtensionVersion{1, 0}}, + {"zve32f", RISCVExtensionVersion{1, 0}}, + {"zve64x", RISCVExtensionVersion{1, 0}}, + {"zve64f", RISCVExtensionVersion{1, 0}}, + {"zve64d", RISCVExtensionVersion{1, 0}}, +}; + +static const RISCVSupportedExtension SupportedExperimentalExtensions[] = { {"zbe", RISCVExtensionVersion{0, 93}}, {"zbf", RISCVExtensionVersion{0, 93}}, {"zbm", RISCVExtensionVersion{0, 93}}, {"zbp", RISCVExtensionVersion{0, 93}}, {"zbr", RISCVExtensionVersion{0, 93}}, - {"zbs", RISCVExtensionVersion{1, 0}}, {"zbt", RISCVExtensionVersion{0, 93}}, - - {"zvlsseg", RISCVExtensionVersion{0, 10}}, - - {"zfhmin", RISCVExtensionVersion{0, 1}}, - {"zfh", RISCVExtensionVersion{0, 1}}, }; static bool stripExperimentalPrefix(StringRef &Ext) { @@ -78,9 +110,9 @@ static bool stripExperimentalPrefix(StringRef &Ext) { // NOTE: This function is NOT able to take empty strings or strings that only // have version numbers and no extension name. It assumes the extension name // will be at least more than one character. -static size_t findFirstNonVersionCharacter(const StringRef &Ext) { - if (Ext.size() == 0) - llvm_unreachable("Already guarded by if-statement in ::parseArchString"); +static size_t findFirstNonVersionCharacter(StringRef Ext) { + assert(!Ext.empty() && + "Already guarded by if-statement in ::parseArchString"); int Pos = Ext.size() - 1; while (Pos > 0 && isDigit(Ext[Pos])) @@ -276,16 +308,13 @@ bool RISCVISAInfo::compareExtension(const std::string &LHS, void RISCVISAInfo::toFeatures( std::vector<StringRef> &Features, std::function<StringRef(const Twine &)> StrAlloc) const { - for (auto &Ext : Exts) { + for (auto const &Ext : Exts) { StringRef ExtName = Ext.first; if (ExtName == "i") continue; - if (ExtName == "zvlsseg") { - Features.push_back("+experimental-v"); - Features.push_back("+experimental-zvlsseg"); - } else if (isExperimentalExtension(ExtName)) { + if (isExperimentalExtension(ExtName)) { Features.push_back(StrAlloc("+experimental-" + ExtName)); } else { Features.push_back(StrAlloc("+" + ExtName)); @@ -434,6 +463,8 @@ RISCVISAInfo::parseFeatures(unsigned XLen, ISAInfo->updateImplication(); ISAInfo->updateFLen(); + ISAInfo->updateMinVLen(); + ISAInfo->updateMaxELen(); if (Error Result = ISAInfo->checkDependency()) return std::move(Result); @@ -657,6 +688,8 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension, ISAInfo->updateImplication(); ISAInfo->updateFLen(); + ISAInfo->updateMinVLen(); + ISAInfo->updateMaxELen(); if (Error Result = ISAInfo->checkDependency()) return std::move(Result); @@ -669,6 +702,12 @@ Error RISCVISAInfo::checkDependency() { bool HasE = Exts.count("e") == 1; bool HasD = Exts.count("d") == 1; bool HasF = Exts.count("f") == 1; + bool HasZve32x = Exts.count("zve32x") == 1; + bool HasZve32f = Exts.count("zve32f") == 1; + bool HasZve64d = Exts.count("zve64d") == 1; + bool HasV = Exts.count("v") == 1; + bool HasVector = HasZve32x || HasV; + bool HasZvl = MinVLen != 0; if (HasE && !IsRv32) return createStringError( @@ -683,6 +722,29 @@ Error RISCVISAInfo::checkDependency() { return createStringError(errc::invalid_argument, "d requires f extension to also be specified"); + // FIXME: Consider Zfinx in the future + if (HasZve32f && !HasF) + return createStringError( + errc::invalid_argument, + "zve32f requires f extension to also be specified"); + + // FIXME: Consider Zdinx in the future + if (HasZve64d && !HasD) + return createStringError( + errc::invalid_argument, + "zve64d requires d extension to also be specified"); + + if (HasZvl && !HasVector) + return createStringError( + errc::invalid_argument, + "zvl*b requires v or zve* extension to also be specified"); + + // Could not implement Zve* extension and the V extension at the same time. + if (HasZve32x && HasV) + return createStringError( + errc::invalid_argument, + "It is illegal to specify the v extension with zve* extensions"); + // Additional dependency checks. // TODO: The 'q' extension requires rv64. // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'. @@ -690,8 +752,27 @@ Error RISCVISAInfo::checkDependency() { return Error::success(); } -static const char *ImpliedExtsV[] = {"zvlsseg"}; +static const char *ImpliedExtsV[] = {"zvl128b", "f", "d"}; static const char *ImpliedExtsZfh[] = {"zfhmin"}; +static const char *ImpliedExtsZve64d[] = {"zve64f"}; +static const char *ImpliedExtsZve64f[] = {"zve64x", "zve32f"}; +static const char *ImpliedExtsZve64x[] = {"zve32x", "zvl64b"}; +static const char *ImpliedExtsZve32f[] = {"zve32x"}; +static const char *ImpliedExtsZve32x[] = {"zvl32b"}; +static const char *ImpliedExtsZvl65536b[] = {"zvl32768b"}; +static const char *ImpliedExtsZvl32768b[] = {"zvl16384b"}; +static const char *ImpliedExtsZvl16384b[] = {"zvl8192b"}; +static const char *ImpliedExtsZvl8192b[] = {"zvl4096b"}; +static const char *ImpliedExtsZvl4096b[] = {"zvl2048b"}; +static const char *ImpliedExtsZvl2048b[] = {"zvl1024b"}; +static const char *ImpliedExtsZvl1024b[] = {"zvl512b"}; +static const char *ImpliedExtsZvl512b[] = {"zvl256b"}; +static const char *ImpliedExtsZvl256b[] = {"zvl128b"}; +static const char *ImpliedExtsZvl128b[] = {"zvl64b"}; +static const char *ImpliedExtsZvl64b[] = {"zvl32b"}; +static const char *ImpliedExtsZk[] = {"zkn", "zkt", "zkr"}; +static const char *ImpliedExtsZkn[] = {"zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"}; +static const char *ImpliedExtsZks[] = {"zbkb", "zbkc", "zbkx", "zksed", "zksh"}; struct ImpliedExtsEntry { StringLiteral Name; @@ -707,6 +788,25 @@ struct ImpliedExtsEntry { static constexpr ImpliedExtsEntry ImpliedExts[] = { {{"v"}, {ImpliedExtsV}}, {{"zfh"}, {ImpliedExtsZfh}}, + {{"zk"}, {ImpliedExtsZk}}, + {{"zkn"}, {ImpliedExtsZkn}}, + {{"zks"}, {ImpliedExtsZks}}, + {{"zve32f"}, {ImpliedExtsZve32f}}, + {{"zve32x"}, {ImpliedExtsZve32x}}, + {{"zve64d"}, {ImpliedExtsZve64d}}, + {{"zve64f"}, {ImpliedExtsZve64f}}, + {{"zve64x"}, {ImpliedExtsZve64x}}, + {{"zvl1024b"}, {ImpliedExtsZvl1024b}}, + {{"zvl128b"}, {ImpliedExtsZvl128b}}, + {{"zvl16384b"}, {ImpliedExtsZvl16384b}}, + {{"zvl2048b"}, {ImpliedExtsZvl2048b}}, + {{"zvl256b"}, {ImpliedExtsZvl256b}}, + {{"zvl32768b"}, {ImpliedExtsZvl32768b}}, + {{"zvl4096b"}, {ImpliedExtsZvl4096b}}, + {{"zvl512b"}, {ImpliedExtsZvl512b}}, + {{"zvl64b"}, {ImpliedExtsZvl64b}}, + {{"zvl65536b"}, {ImpliedExtsZvl65536b}}, + {{"zvl8192b"}, {ImpliedExtsZvl8192b}}, }; void RISCVISAInfo::updateImplication() { @@ -721,12 +821,25 @@ void RISCVISAInfo::updateImplication() { } assert(llvm::is_sorted(ImpliedExts) && "Table not sorted by Name"); - for (auto &Ext : Exts) { - auto I = llvm::lower_bound(ImpliedExts, Ext.first); - if (I != std::end(ImpliedExts) && I->Name == Ext.first) { - for (auto &ImpliedExt : I->Exts) { + + // This loop may execute over 1 iteration since implication can be layered + // Exits loop if no more implication is applied + SmallSetVector<StringRef, 16> WorkList; + for (auto const &Ext : Exts) + WorkList.insert(Ext.first); + + while (!WorkList.empty()) { + StringRef ExtName = WorkList.pop_back_val(); + auto I = llvm::lower_bound(ImpliedExts, ExtName); + if (I != std::end(ImpliedExts) && I->Name == ExtName) { + for (const char *ImpliedExt : I->Exts) { + if (WorkList.count(ImpliedExt)) + continue; + if (Exts.count(ImpliedExt)) + continue; auto Version = findDefaultVersion(ImpliedExt); addExtension(ImpliedExt, Version->Major, Version->Minor); + WorkList.insert(ImpliedExt); } } } @@ -741,6 +854,41 @@ void RISCVISAInfo::updateFLen() { FLen = 32; } +void RISCVISAInfo::updateMinVLen() { + for (auto const &Ext : Exts) { + StringRef ExtName = Ext.first; + bool IsZvlExt = ExtName.consume_front("zvl") && ExtName.consume_back("b"); + if (IsZvlExt) { + unsigned ZvlLen; + if (!ExtName.getAsInteger(10, ZvlLen)) + MinVLen = std::max(MinVLen, ZvlLen); + } + } +} + +void RISCVISAInfo::updateMaxELen() { + // handles EEW restriction by sub-extension zve + for (auto const &Ext : Exts) { + StringRef ExtName = Ext.first; + bool IsZveExt = ExtName.consume_front("zve"); + if (IsZveExt) { + if (ExtName.back() == 'f') + MaxELenFp = std::max(MaxELenFp, 32u); + if (ExtName.back() == 'd') + MaxELenFp = std::max(MaxELenFp, 64u); + ExtName = ExtName.drop_back(); + unsigned ZveELen; + ExtName.getAsInteger(10, ZveELen); + MaxELen = std::max(MaxELen, ZveELen); + } + if (ExtName == "v") { + MaxELenFp = 64; + MaxELen = 64; + return; + } + } +} + std::string RISCVISAInfo::toString() const { std::string Buffer; raw_string_ostream Arch(Buffer); @@ -748,7 +896,7 @@ std::string RISCVISAInfo::toString() const { Arch << "rv" << XLen; ListSeparator LS("_"); - for (auto &Ext : Exts) { + for (auto const &Ext : Exts) { StringRef ExtName = Ext.first; auto ExtInfo = Ext.second; Arch << LS << ExtName; @@ -757,3 +905,17 @@ std::string RISCVISAInfo::toString() const { return Arch.str(); } + +std::vector<std::string> RISCVISAInfo::toFeatureVector() const { + std::vector<std::string> FeatureVector; + for (auto const &Ext : Exts) { + std::string ExtName = Ext.first; + if (ExtName == "i") // i is not recognized in clang -cc1 + continue; + std::string Feature = isExperimentalExtension(ExtName) + ? "+experimental-" + ExtName + : "+" + ExtName; + FeatureVector.push_back(Feature); + } + return FeatureVector; +} |