[lld] r322117 - [COFF] Process /EXPORT option in fastpath

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 9 12:36:42 PST 2018


Author: ruiu
Date: Tue Jan  9 12:36:42 2018
New Revision: 322117

URL: http://llvm.org/viewvc/llvm-project?rev=322117&view=rev
Log:
[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

Modified:
    lld/trunk/COFF/Driver.cpp
    lld/trunk/COFF/Driver.h
    lld/trunk/COFF/DriverUtils.cpp

Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=322117&r1=322116&r2=322117&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Tue Jan  9 12:36:42 2018
@@ -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(Strin
     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;

Modified: lld/trunk/COFF/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.h?rev=322117&r1=322116&r2=322117&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.h (original)
+++ lld/trunk/COFF/Driver.h Tue Jan  9 12:36:42 2018
@@ -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.

Modified: lld/trunk/COFF/DriverUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DriverUtils.cpp?rev=322117&r1=322116&r2=322117&view=diff
==============================================================================
--- lld/trunk/COFF/DriverUtils.cpp (original)
+++ lld/trunk/COFF/DriverUtils.cpp Tue Jan  9 12:36:42 2018
@@ -751,19 +751,30 @@ opt::InputArgList ArgParser::parse(Array
 }
 
 // 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




More information about the llvm-commits mailing list