[PATCH] D73667: Speed up compilation of ASTImporter

Reid Kleckner via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 29 14:44:44 PST 2020


rnk created this revision.
rnk added reviewers: rsmith, aaron.ballman.
Herald added a reviewer: martong.
Herald added a reviewer: a.sidorin.
Herald added a reviewer: shafik.
Herald added subscribers: llvm-commits, teemperor.
Herald added projects: clang, LLVM.
rnk updated this revision to Diff 241297.
rnk added a comment.
Herald added a subscriber: rnkovacs.

- remove unintended hack to test MSVC


Avoid recursively instantiating importSeq. Use initializer list
expansion to stamp out a single instantiation of std::tuple of the
deduced sequence of types, and thread the error around that tuple type.
Avoids needlessly instantiating std::tuple N-1 times.

new time to compile: 0m25.985s
old time to compile: 0m35.563s

new obj size: 10,000kb
old obj size: 12,332kb

I found the slow TU by looking at ClangBuildAnalyzer results, and looked
at -ftime-trace for the file in chrome://tracing to find this.

Tested with: clang-cl, MSVC, and GCC.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D73667

Files:
  clang/lib/AST/ASTImporter.cpp


Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -186,32 +186,33 @@
       return import(*From);
     }
 
-    template <class T>
-    Expected<std::tuple<T>>
-    importSeq(const T &From) {
-      Expected<T> ToOrErr = import(From);
-      if (!ToOrErr)
-        return ToOrErr.takeError();
-      return std::make_tuple<T>(std::move(*ToOrErr));
+    // Helper for error management in importSeq.
+    template <typename T> T checkImport(Error &Err, const T &From) {
+      // Don't attempt to import nodes if we hit an error earlier.
+      if (Err)
+        return T{};
+      Expected<T> MaybeVal = import(From);
+      if (!MaybeVal) {
+        Err = MaybeVal.takeError();
+        return T{};
+      }
+      return *MaybeVal;
     }
 
     // Import multiple objects with a single function call.
     // This should work for every type for which a variant of `import` exists.
     // The arguments are processed from left to right and import is stopped on
     // first error.
-    template <class THead, class... TTail>
-    Expected<std::tuple<THead, TTail...>>
-    importSeq(const THead &FromHead, const TTail &...FromTail) {
-      Expected<std::tuple<THead>> ToHeadOrErr = importSeq(FromHead);
-      if (!ToHeadOrErr)
-        return ToHeadOrErr.takeError();
-      Expected<std::tuple<TTail...>> ToTailOrErr = importSeq(FromTail...);
-      if (!ToTailOrErr)
-        return ToTailOrErr.takeError();
-      return std::tuple_cat(*ToHeadOrErr, *ToTailOrErr);
+    template <class... Args>
+    Expected<std::tuple<Args...>> importSeq(const Args &... args) {
+      Error E = Error::success();
+      std::tuple<Args...> Res{checkImport(E, args)...};
+      if (E)
+        return std::move(E);
+      return std::move(Res);
     }
 
-// Wrapper for an overload set.
+    // Wrapper for an overload set.
     template <typename ToDeclT> struct CallOverloadedCreateFun {
       template <typename... Args>
       auto operator()(Args &&... args)


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D73667.241297.patch
Type: text/x-patch
Size: 2084 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200129/7a54ae02/attachment.bin>


More information about the cfe-commits mailing list