diff options
| author | Rui Ueyama <ruiu@google.com> | 2018-01-09 20:36:42 +0000 |
|---|---|---|
| committer | Rui Ueyama <ruiu@google.com> | 2018-01-09 20:36:42 +0000 |
| commit | 5fa0d6e4a2bd3f9de565ce13c3107b91a2530ad3 (patch) | |
| tree | b0d3d4bbfa8170a87ca7d0886bdedf6d87cae1fa | |
| parent | 72b3855bf58702b3731d74f8eb24f8c5dfb150d8 (diff) | |
| download | bcm5719-llvm-5fa0d6e4a2bd3f9de565ce13c3107b91a2530ad3.tar.gz bcm5719-llvm-5fa0d6e4a2bd3f9de565ce13c3107b91a2530ad3.zip | |
[COFF] Process /EXPORT option in fastpath
Patch by Takuto Ikuta.
This patch reduces lld link time of chromium's blink_core.dll in
component build.
Total size of input argument in .directives become nearly 300MB in the
build and almost all its content are /EXPORT.
To reduce time of parsing too many /EXPORT option in the build, I
introduce fastpath for /EXPORT in ArgParser::parseDirectives.
On my desktop machine, 4 times stats of the link time are like below.
Improved around 20%.
This patch
TotalSeconds : 8.6217627
TotalSeconds : 8.5402175
TotalSeconds : 8.6855853
TotalSeconds : 8.3624441
Ave : 8.5525024
master
TotalSeconds : 10.9975031
TotalSeconds : 11.3409428
TotalSeconds : 10.6332897
TotalSeconds : 10.7650687
Ave : 10.934201075
llvm-svn: 322117
| -rw-r--r-- | lld/COFF/Driver.cpp | 43 | ||||
| -rw-r--r-- | lld/COFF/Driver.h | 6 | ||||
| -rw-r--r-- | lld/COFF/DriverUtils.cpp | 21 | ||||
| -rw-r--r-- | llvm/include/llvm/Option/ArgList.h | 2 |
4 files changed, 45 insertions, 27 deletions
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 23ff0501da8..7bddffc5bf4 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -227,7 +227,29 @@ static bool isDecorated(StringRef Sym) { void LinkerDriver::parseDirectives(StringRef S) { ArgParser Parser; // .drectve is always tokenized using Windows shell rules. - opt::InputArgList Args = Parser.parseDirectives(S); + // /EXPORT: option can appear too many times, processing in fastpath. + opt::InputArgList Args; + std::vector<StringRef> Exports; + std::tie(Args, Exports) = Parser.parseDirectives(S); + + for (StringRef E : Exports) { + // If a common header file contains dllexported function + // declarations, many object files may end up with having the + // same /EXPORT options. In order to save cost of parsing them, + // we dedup them first. + if (!DirectivesExports.insert(E).second) + continue; + + Export Exp = parseExport(E); + if (Config->Machine == I386 && Config->MinGW) { + if (!isDecorated(Exp.Name)) + Exp.Name = Saver.save("_" + Exp.Name); + if (!Exp.ExtName.empty() && !isDecorated(Exp.ExtName)) + Exp.ExtName = Saver.save("_" + Exp.ExtName); + } + Exp.Directives = true; + Config->Exports.push_back(Exp); + } for (auto *Arg : Args) { switch (Arg->getOption().getUnaliasedOption().getID()) { @@ -244,25 +266,6 @@ void LinkerDriver::parseDirectives(StringRef S) { case OPT_entry: Config->Entry = addUndefined(mangle(Arg->getValue())); break; - case OPT_export: { - // If a common header file contains dllexported function - // declarations, many object files may end up with having the - // same /EXPORT options. In order to save cost of parsing them, - // we dedup them first. - if (!DirectivesExports.insert(Arg->getValue()).second) - break; - - Export E = parseExport(Arg->getValue()); - if (Config->Machine == I386 && Config->MinGW) { - if (!isDecorated(E.Name)) - E.Name = Saver.save("_" + E.Name); - if (!E.ExtName.empty() && !isDecorated(E.ExtName)) - E.ExtName = Saver.save("_" + E.ExtName); - } - E.Directives = true; - Config->Exports.push_back(E); - break; - } case OPT_failifmismatch: checkFailIfMismatch(Arg->getValue()); break; diff --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h index 3f7fad1038f..bbb6cc97532 100644 --- a/lld/COFF/Driver.h +++ b/lld/COFF/Driver.h @@ -56,8 +56,10 @@ public: llvm::opt::InputArgList parse(StringRef S) { return parse(tokenize(S)); } // Tokenizes a given string and then parses as command line options in - // .drectve section. - llvm::opt::InputArgList parseDirectives(StringRef S); + // .drectve section. /EXPORT options are returned in second element + // to be processed in fastpath. + std::pair<llvm::opt::InputArgList, std::vector<StringRef>> + parseDirectives(StringRef S); private: // Parses command line options. diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp index e0641e04a01..0fe9e48b403 100644 --- a/lld/COFF/DriverUtils.cpp +++ b/lld/COFF/DriverUtils.cpp @@ -751,19 +751,30 @@ opt::InputArgList ArgParser::parse(ArrayRef<const char *> Argv) { } // Tokenizes and parses a given string as command line in .drective section. -opt::InputArgList ArgParser::parseDirectives(StringRef S) { - // Make InputArgList from string vectors. +// /EXPORT options are processed in fastpath. +std::pair<opt::InputArgList, std::vector<StringRef>> +ArgParser::parseDirectives(StringRef S) { + std::vector<StringRef> Exports; + SmallVector<const char *, 16> Rest; + + for (StringRef Tok : tokenize(S)) { + if (Tok.startswith_lower("/export:") || Tok.startswith_lower("-export:")) + Exports.push_back(Tok.substr(strlen("/export:"))); + else + Rest.push_back(Tok.data()); + } + + // Make InputArgList from unparsed string vectors. unsigned MissingIndex; unsigned MissingCount; - opt::InputArgList Args = - Table.ParseArgs(tokenize(S), MissingIndex, MissingCount); + opt::InputArgList Args = Table.ParseArgs(Rest, MissingIndex, MissingCount); if (MissingCount) fatal(Twine(Args.getArgString(MissingIndex)) + ": missing argument"); for (auto *Arg : Args.filtered(OPT_UNKNOWN)) warn("ignoring unknown argument: " + Arg->getSpelling()); - return Args; + return {std::move(Args), std::move(Exports)}; } // link.exe has an interesting feature. If LINK or _LINK_ environment diff --git a/llvm/include/llvm/Option/ArgList.h b/llvm/include/llvm/Option/ArgList.h index aaea68bf8e2..a80921fa842 100644 --- a/llvm/include/llvm/Option/ArgList.h +++ b/llvm/include/llvm/Option/ArgList.h @@ -390,6 +390,8 @@ private: void releaseMemory(); public: + InputArgList() : NumInputArgStrings(0) {} + InputArgList(const char* const *ArgBegin, const char* const *ArgEnd); InputArgList(InputArgList &&RHS) |

