Skip to content

Commit 3b1a686

Browse files
authored
[clang][deps] Generate command lines lazily (#65691)
This patch makes the generation of command lines for modular dependencies lazy/on-demand. That operation is somewhat expensive and prior to this patch used to be performed multiple times for the identical `ModuleDeps` (i.e. when they were imported from multiple different TUs).
1 parent 904ac6f commit 3b1a686

File tree

3 files changed

+37
-13
lines changed

3 files changed

+37
-13
lines changed

clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h

+10-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <optional>
2424
#include <string>
2525
#include <unordered_map>
26+
#include <variant>
2627

2728
namespace clang {
2829
namespace tooling {
@@ -136,9 +137,15 @@ struct ModuleDeps {
136137
/// determined that the differences are benign for this compilation.
137138
std::vector<ModuleID> ClangModuleDeps;
138139

139-
/// Compiler invocation that can be used to build this module. Does not
140-
/// include argv[0].
141-
std::vector<std::string> BuildArguments;
140+
/// Get (or compute) the compiler invocation that can be used to build this
141+
/// module. Does not include argv[0].
142+
const std::vector<std::string> &getBuildArguments();
143+
144+
private:
145+
friend class ModuleDepCollectorPP;
146+
147+
std::variant<std::monostate, CowCompilerInvocation, std::vector<std::string>>
148+
BuildInfo;
142149
};
143150

144151
class ModuleDepCollector;

clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp

+9-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ using namespace clang;
2121
using namespace tooling;
2222
using namespace dependencies;
2323

24+
const std::vector<std::string> &ModuleDeps::getBuildArguments() {
25+
assert(!std::holds_alternative<std::monostate>(BuildInfo) &&
26+
"Using uninitialized ModuleDeps");
27+
if (const auto *CI = std::get_if<CowCompilerInvocation>(&BuildInfo))
28+
BuildInfo = CI->getCC1CommandLine();
29+
return std::get<std::vector<std::string>>(BuildInfo);
30+
}
31+
2432
static void optimizeHeaderSearchOpts(HeaderSearchOptions &Opts,
2533
ASTReader &Reader,
2634
const serialization::ModuleFile &MF) {
@@ -532,7 +540,7 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
532540
// Finish the compiler invocation. Requires dependencies and the context hash.
533541
MDC.addOutputPaths(CI, MD);
534542

535-
MD.BuildArguments = CI.getCC1CommandLine();
543+
MD.BuildInfo = std::move(CI);
536544

537545
return MD.ID;
538546
}

clang/tools/clang-scan-deps/ClangScanDeps.cpp

+18-9
Original file line numberDiff line numberDiff line change
@@ -351,14 +351,23 @@ class FullDeps {
351351
}
352352

353353
void mergeDeps(ModuleDepsGraph Graph, size_t InputIndex) {
354-
std::unique_lock<std::mutex> ul(Lock);
355-
for (const ModuleDeps &MD : Graph) {
356-
auto I = Modules.find({MD.ID, 0});
357-
if (I != Modules.end()) {
358-
I->first.InputIndex = std::min(I->first.InputIndex, InputIndex);
359-
continue;
354+
std::vector<ModuleDeps *> NewMDs;
355+
{
356+
std::unique_lock<std::mutex> ul(Lock);
357+
for (const ModuleDeps &MD : Graph) {
358+
auto I = Modules.find({MD.ID, 0});
359+
if (I != Modules.end()) {
360+
I->first.InputIndex = std::min(I->first.InputIndex, InputIndex);
361+
continue;
362+
}
363+
auto Res = Modules.insert(I, {{MD.ID, InputIndex}, std::move(MD)});
364+
NewMDs.push_back(&Res->second);
360365
}
361-
Modules.insert(I, {{MD.ID, InputIndex}, std::move(MD)});
366+
// First call to \c getBuildArguments is somewhat expensive. Let's call it
367+
// on the current thread (instead of the main one), and outside the
368+
// critical section.
369+
for (ModuleDeps *MD : NewMDs)
370+
(void)MD->getBuildArguments();
362371
}
363372
}
364373

@@ -382,7 +391,7 @@ class FullDeps {
382391
/*ShouldOwnClient=*/false);
383392

384393
for (auto &&M : Modules)
385-
if (roundTripCommand(M.second.BuildArguments, *Diags))
394+
if (roundTripCommand(M.second.getBuildArguments(), *Diags))
386395
return true;
387396

388397
for (auto &&I : Inputs)
@@ -411,7 +420,7 @@ class FullDeps {
411420
{"file-deps", toJSONSorted(MD.FileDeps)},
412421
{"clang-module-deps", toJSONSorted(MD.ClangModuleDeps)},
413422
{"clang-modulemap-file", MD.ClangModuleMapFile},
414-
{"command-line", MD.BuildArguments},
423+
{"command-line", MD.getBuildArguments()},
415424
};
416425
OutModules.push_back(std::move(O));
417426
}

0 commit comments

Comments
 (0)