From: Fangrui Song Date: Mon, 12 Jul 2021 16:03:33 +0000 (-0700) Subject: [llvm-objcopy] Improve performance of long pattern lists X-Git-Tag: llvmorg-14-init~1739 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0144e625b9672d27b25196346134a7ac40e00e29;p=platform%2Fupstream%2Fllvm.git [llvm-objcopy] Improve performance of long pattern lists Some users use a long list of fixed patterns (PR50404) and O(|patterns|*|symbols|) can be too slow. Such usage typically does not use --regex or --wildcard. We can use a DenseSet to optimize name lookups. Reviewed By: jhenderson Differential Revision: https://reviews.llvm.org/D105218 --- diff --git a/llvm/tools/llvm-objcopy/CommonConfig.h b/llvm/tools/llvm-objcopy/CommonConfig.h index 49a77e1..131ce5c 100644 --- a/llvm/tools/llvm-objcopy/CommonConfig.h +++ b/llvm/tools/llvm-objcopy/CommonConfig.h @@ -10,6 +10,7 @@ #define LLVM_TOOLS_LLVM_OBJCOPY_COMMONCONFIG_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/CachedHashString.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" @@ -113,6 +114,11 @@ public: llvm::function_ref ErrorCallback); bool isPositiveMatch() const { return IsPositiveMatch; } + Optional getName() const { + if (!R && !G) + return Name; + return None; + } bool operator==(StringRef S) const { return R ? R->match(S) : G ? G->match(S) : Name == S; } @@ -122,23 +128,32 @@ public: // Matcher that checks symbol or section names against the command line flags // provided for that option. class NameMatcher { - std::vector PosMatchers; + DenseSet PosNames; + std::vector PosPatterns; std::vector NegMatchers; public: Error addMatcher(Expected Matcher) { if (!Matcher) return Matcher.takeError(); - if (Matcher->isPositiveMatch()) - PosMatchers.push_back(std::move(*Matcher)); - else + if (Matcher->isPositiveMatch()) { + if (Optional MaybeName = Matcher->getName()) + PosNames.insert(CachedHashStringRef(*MaybeName)); + else + PosPatterns.push_back(std::move(*Matcher)); + } else { NegMatchers.push_back(std::move(*Matcher)); + } return Error::success(); } bool matches(StringRef S) const { - return is_contained(PosMatchers, S) && !is_contained(NegMatchers, S); + return (PosNames.contains(CachedHashStringRef(S)) || + is_contained(PosPatterns, S)) && + !is_contained(NegMatchers, S); + } + bool empty() const { + return PosNames.empty() && PosPatterns.empty() && NegMatchers.empty(); } - bool empty() const { return PosMatchers.empty() && NegMatchers.empty(); } }; enum class SymbolFlag {