From c0bbf1ba9bd40fdbe1cc64d1e6b6cdf63ec2fb81 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Wed, 24 Jul 2024 08:40:27 -0700 Subject: [PATCH] Remove multimap usage from `memoizeDeclsByName` (#4821) * Ensure we use iterator traits to query for iterators' value type. This way we can wrap over std::vector iterator Signed-off-by: Anton Korobeynikov * Use better data structures to store memoized declarations Signed-off-by: Anton Korobeynikov --------- Signed-off-by: Anton Korobeynikov --- .../resolveReferences/resolveReferences.cpp | 6 +++--- .../resolveReferences/resolveReferences.h | 19 +++++++++++-------- lib/enumerator.h | 12 ++++++------ 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/frontends/common/resolveReferences/resolveReferences.cpp b/frontends/common/resolveReferences/resolveReferences.cpp index 0db01c1b7d3..32f44377779 100644 --- a/frontends/common/resolveReferences/resolveReferences.cpp +++ b/frontends/common/resolveReferences/resolveReferences.cpp @@ -38,10 +38,10 @@ const std::vector &ResolutionContext::memoizeDeclarati return (namespaceDecls[ns] = std::move(decls)); } -std::unordered_multimap &ResolutionContext::memoizeDeclsByName( +ResolutionContext::NamespaceDeclsByName &ResolutionContext::memoizeDeclsByName( const IR::INamespace *ns) const { auto &namesToDecls = namespaceDeclNames[ns]; - for (const auto *d : getDeclarations(ns)) namesToDecls.emplace(d->getName().name, d); + for (const auto *d : getDeclarations(ns)) namesToDecls[d->getName().name].push_back(d); return namesToDecls; } @@ -63,7 +63,7 @@ std::vector ResolutionContext::lookup(const IR::INames if (const auto *gen = current->to()) { // FIXME: implement range filtering without enumerator wrappers - auto *decls = Util::enumerate(getDeclsByName(gen, name)); + auto *decls = getDeclsByName(gen, name); switch (type) { case P4::ResolutionType::Any: break; diff --git a/frontends/common/resolveReferences/resolveReferences.h b/frontends/common/resolveReferences/resolveReferences.h index 9d6ef4b1aef..ae477219ff2 100644 --- a/frontends/common/resolveReferences/resolveReferences.h +++ b/frontends/common/resolveReferences/resolveReferences.h @@ -18,6 +18,7 @@ limitations under the License. #define COMMON_RESOLVEREFERENCES_RESOLVEREFERENCES_H_ #include "absl/container/flat_hash_map.h" +#include "absl/container/inlined_vector.h" #include "ir/ir.h" #include "lib/cstring.h" #include "lib/iterator_range.h" @@ -36,17 +37,17 @@ class ResolutionContext : virtual public Visitor, public DeclarationLookup { const std::vector &memoizeDeclarations( const IR::INamespace *ns) const; + using DeclsVector = absl::InlinedVector; + using NamespaceDeclsByName = absl::flat_hash_map; + // Returns a mapping from name -> decl for the given namespace, and caches the result for // future lookups. - std::unordered_multimap &memoizeDeclsByName( - const IR::INamespace *ns) const; + NamespaceDeclsByName &memoizeDeclsByName(const IR::INamespace *ns) const; mutable absl::flat_hash_map, Util::Hash> namespaceDecls; - mutable absl::flat_hash_map, - Util::Hash> + mutable absl::flat_hash_map namespaceDeclNames; protected: @@ -100,11 +101,13 @@ class ResolutionContext : virtual public Visitor, public DeclarationLookup { /// Returns the set of decls with the given name that exist in the given namespace. auto getDeclsByName(const IR::INamespace *ns, cstring name) const { auto nsIt = namespaceDeclNames.find(ns); - auto &namesToDecls = + const auto &namesToDecls = nsIt != namespaceDeclNames.end() ? nsIt->second : memoizeDeclsByName(ns); - auto decls = Values(namesToDecls.equal_range(name)); - return Util::iterator_range(decls.begin(), decls.end()); + auto decls = namesToDecls.find(name); + if (decls == namesToDecls.end()) + return Util::Enumerator::emptyEnumerator(); + return Util::enumerate(decls->second); } }; diff --git a/lib/enumerator.h b/lib/enumerator.h index 5ae1f5ccab7..bd71c487252 100644 --- a/lib/enumerator.h +++ b/lib/enumerator.h @@ -196,17 +196,17 @@ class Enumerator { /// A generic iterator returning elements of type T. template -class IteratorEnumerator : public Enumerator { +class IteratorEnumerator : public Enumerator::value_type> { protected: Iter begin; Iter end; Iter current; const char *name; - friend class Enumerator; + friend class Enumerator::value_type>; public: IteratorEnumerator(Iter begin, Iter end, const char *name) - : Enumerator(), + : Enumerator::value_type>(), begin(begin), end(end), current(begin), @@ -241,7 +241,7 @@ class IteratorEnumerator : public Enumerator { throw std::runtime_error("Unexpected enumerator state"); } - typename Iter::value_type getCurrent() const { + typename std::iterator_traits::value_type getCurrent() const { switch (this->state) { case EnumeratorState::NotStarted: throw std::logic_error("You cannot call 'getCurrent' before 'moveNext'"); @@ -638,12 +638,12 @@ bool EnumeratorHandle::operator!=(const EnumeratorHandle &other) const { } template -Enumerator *enumerate(Iter begin, Iter end) { +Enumerator::value_type> *enumerate(Iter begin, Iter end) { return new IteratorEnumerator(begin, end, "iterator"); } template -Enumerator *enumerate(iterator_range range) { +Enumerator::value_type> *enumerate(iterator_range range) { return new IteratorEnumerator(range.begin(), range.end(), "range"); }