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)
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)
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits