From 1419c89670953b969fcc1c474a258c7475d8e7df Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Fri, 9 May 2025 07:45:20 -0500 Subject: [PATCH 1/2] [flang][OpenMP] Handle multiple spellings in OmpDirectiveNameParser Collect all spellings from all supported OpenMP versions before parsing. Break up the list of spellings by the initial letter to speed up parsing a little. --- flang/lib/Parser/openmp-parsers.cpp | 49 +++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 30b5d4f9513a7..29701a616d4b0 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSet.h" #include "llvm/Frontend/OpenMP/OMP.h" // OpenMP Directives and Clauses @@ -104,8 +105,13 @@ struct OmpDirectiveNameParser { using Token = TokenStringMatch; std::optional Parse(ParseState &state) const { + if (state.BytesRemaining() == 0) { + return std::nullopt; + } auto begin{state.GetLocation()}; - for (const NameWithId &nid : directives()) { + char next{static_cast(std::tolower(*begin))}; + + for (const NameWithId &nid : directives_starting_with(next)) { if (attempt(Token(nid.first.data())).Parse(state)) { OmpDirectiveName n; n.v = nid.second; @@ -118,30 +124,47 @@ struct OmpDirectiveNameParser { private: using NameWithId = std::pair; + using ConstIterator = std::vector::const_iterator; - llvm::iterator_range directives() const; - void initTokens(NameWithId *) const; + llvm::iterator_range + directives_starting_with(char initial) const; + void initTokens(std::vector[]) const; }; -llvm::iterator_range -OmpDirectiveNameParser::directives() const { - static NameWithId table[llvm::omp::Directive_enumSize]; +llvm::iterator_range +OmpDirectiveNameParser::directives_starting_with(char initial) const { + static const std::vector empty{}; + if (initial < 'a' || initial > 'z') { + return llvm::make_range(std::cbegin(empty), std::cend(empty)); + } + + static std::vector table['z' - 'a' + 1]; [[maybe_unused]] static bool init = (initTokens(table), true); - return llvm::make_range(std::cbegin(table), std::cend(table)); + + int index = initial - 'a'; + return llvm::make_range(std::cbegin(table[index]), std::cend(table[index])); } -void OmpDirectiveNameParser::initTokens(NameWithId *table) const { +void OmpDirectiveNameParser::initTokens(std::vector table[]) const { for (size_t i{0}, e{llvm::omp::Directive_enumSize}; i != e; ++i) { + llvm::StringSet spellings; auto id{static_cast(i)}; - llvm::StringRef name{ - llvm::omp::getOpenMPDirectiveName(id, llvm::omp::FallbackVersion)}; - table[i] = std::make_pair(name.str(), id); + for (unsigned version : llvm::omp::getOpenMPVersions()) { + spellings.insert(llvm::omp::getOpenMPDirectiveName(id, version)); + } + for (auto &[name, _] : spellings) { + char initial{static_cast(std::tolower(name.front()))}; + table[initial - 'a'].emplace_back(name.str(), id); + } } // Sort the table with respect to the directive name length in a descending // order. This is to make sure that longer names are tried first, before // any potential prefix (e.g. "target update" before "target"). - std::sort(table, table + llvm::omp::Directive_enumSize, - [](auto &a, auto &b) { return a.first.size() > b.first.size(); }); + for (int initial{'a'}; initial != 'z' + 1; ++initial) { + llvm::stable_sort(table[initial - 'a'], [](auto &a, auto &b) { + return a.first.size() > b.first.size(); + }); + } } // --- Modifier helpers ----------------------------------------------- From 1dd6916ae6c7bd360e1c603b0cb9fd3b942233fc Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Wed, 9 Jul 2025 08:22:33 -0500 Subject: [PATCH 2/2] format --- flang/lib/Parser/openmp-parsers.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 29701a616d4b0..fdf96dffeb8ed 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -126,8 +126,8 @@ struct OmpDirectiveNameParser { using NameWithId = std::pair; using ConstIterator = std::vector::const_iterator; - llvm::iterator_range - directives_starting_with(char initial) const; + llvm::iterator_range directives_starting_with( + char initial) const; void initTokens(std::vector[]) const; }; @@ -161,9 +161,8 @@ void OmpDirectiveNameParser::initTokens(std::vector table[]) const { // order. This is to make sure that longer names are tried first, before // any potential prefix (e.g. "target update" before "target"). for (int initial{'a'}; initial != 'z' + 1; ++initial) { - llvm::stable_sort(table[initial - 'a'], [](auto &a, auto &b) { - return a.first.size() > b.first.size(); - }); + llvm::stable_sort(table[initial - 'a'], + [](auto &a, auto &b) { return a.first.size() > b.first.size(); }); } }