Skip to content

Commit 0ffabf4

Browse files
authored
[clang][deps] Use the caching VFS even in the 'preprocess' mode (#168970)
The dependency scanner worker's VFS originally unconditionally did two things: file system access caching and dependency directives extraction. That's why `clang-scan-deps -mode preprocess` avoided using the VFS entirely. Since then, the dependency directives extraction was made lazy/on-demand/optional, meaning it should be possible to use only the caching parts of the VFS. This PR does exactly that, speeding up `clang-scan-deps -mode preprocess` on my config of Clang/LLVM from ~80s to ~38s. (For comparison, `clang-scan-deps -mode preprocess-dependency-directives` runs in ~13s.) (The real motivation was to simplify the VFS handling in the scanner, this is just a nice side-effect.)
1 parent 838ad0e commit 0ffabf4

File tree

3 files changed

+37
-39
lines changed

3 files changed

+37
-39
lines changed

clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,9 @@ class DependencyScanningWorker {
8686
/// Construct a dependency scanning worker.
8787
///
8888
/// @param Service The parent service. Must outlive the worker.
89-
/// @param FS The filesystem for the worker to use.
89+
/// @param BaseFS The filesystem for the worker to use.
9090
DependencyScanningWorker(DependencyScanningService &Service,
91-
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS);
91+
IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS);
9292

9393
~DependencyScanningWorker();
9494

@@ -157,31 +157,26 @@ class DependencyScanningWorker {
157157
DependencyActionController &Controller);
158158
bool finalizeCompilerInstance();
159159

160-
llvm::vfs::FileSystem &getVFS() const { return *BaseFS; }
160+
llvm::vfs::FileSystem &getVFS() const { return *DepFS; }
161161

162162
private:
163163
/// The parent dependency scanning service.
164164
DependencyScanningService &Service;
165165
std::shared_ptr<PCHContainerOperations> PCHContainerOps;
166-
/// The file system to be used during the scan.
167-
/// This is either \c FS passed in the constructor (when performing canonical
168-
/// preprocessing), or \c DepFS (when performing dependency directives scan).
169-
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS;
170-
/// When performing dependency directives scan, this is the caching (and
171-
/// dependency-directives-extracting) filesystem overlaid on top of \c FS
172-
/// (passed in the constructor).
173-
llvm::IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS;
166+
/// This is the caching (and optionally dependency-directives-providing) VFS
167+
/// overlaid on top of the base VFS passed in the constructor.
168+
IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS;
174169

175170
friend CompilerInstanceWithContext;
176171
std::unique_ptr<CompilerInstanceWithContext> CIWithContext;
177172

178-
/// Private helper functions.
179-
bool scanDependencies(StringRef WorkingDirectory,
180-
const std::vector<std::string> &CommandLine,
181-
DependencyConsumer &Consumer,
182-
DependencyActionController &Controller,
183-
DiagnosticConsumer &DC,
184-
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS);
173+
/// Actually carries out the scan. If \c OverlayFS is provided, it must be
174+
/// based on top of DepFS.
175+
bool scanDependencies(
176+
StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
177+
DependencyConsumer &Consumer, DependencyActionController &Controller,
178+
DiagnosticConsumer &DC,
179+
IntrusiveRefCntPtr<llvm::vfs::FileSystem> OverlayFS = nullptr);
185180
};
186181

187182
} // end namespace dependencies

clang/lib/Tooling/DependencyScanning/DependencyScannerImpl.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -524,8 +524,8 @@ bool dependencies::initializeScanCompilerInstance(
524524
// Create a new FileManager to match the invocation's FileSystemOptions.
525525
ScanInstance.createFileManager();
526526

527-
// Use the dependency scanning optimized file system if requested to do so.
528-
if (DepFS) {
527+
// Use DepFS for getting the dependency directives if requested to do so.
528+
if (Service.getMode() == ScanningMode::DependencyDirectivesScan) {
529529
DepFS->resetBypassedPathPrefix();
530530
SmallString<256> ModulesCachePath;
531531
normalizeModuleCachePath(ScanInstance.getFileManager(),
@@ -717,7 +717,7 @@ bool CompilerInstanceWithContext::initialize(DiagnosticConsumer *DC) {
717717
}
718718

719719
std::tie(OverlayFS, CommandLine) = initVFSForByNameScanning(
720-
Worker.BaseFS, CommandLine, CWD, "ScanningByName");
720+
Worker.DepFS, CommandLine, CWD, "ScanningByName");
721721

722722
DiagEngineWithCmdAndOpts = std::make_unique<DignosticsEngineWithDiagOpts>(
723723
CommandLine, OverlayFS, *DiagConsumer);

clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ using namespace dependencies;
1818

1919
DependencyScanningWorker::DependencyScanningWorker(
2020
DependencyScanningService &Service,
21-
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
21+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS)
2222
: Service(Service) {
2323
PCHContainerOps = std::make_shared<PCHContainerOperations>();
2424
// We need to read object files from PCH built outside the scanner.
@@ -28,19 +28,11 @@ DependencyScanningWorker::DependencyScanningWorker(
2828
PCHContainerOps->registerWriter(std::make_unique<RawPCHContainerWriter>());
2929

3030
if (Service.shouldTraceVFS())
31-
FS = llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(std::move(FS));
32-
33-
switch (Service.getMode()) {
34-
case ScanningMode::DependencyDirectivesScan:
35-
DepFS = llvm::makeIntrusiveRefCnt<DependencyScanningWorkerFilesystem>(
36-
Service.getSharedCache(), FS);
37-
BaseFS = DepFS;
38-
break;
39-
case ScanningMode::CanonicalPreprocessing:
40-
DepFS = nullptr;
41-
BaseFS = FS;
42-
break;
43-
}
31+
BaseFS = llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(
32+
std::move(BaseFS));
33+
34+
DepFS = llvm::makeIntrusiveRefCnt<DependencyScanningWorkerFilesystem>(
35+
Service.getSharedCache(), std::move(BaseFS));
4436
}
4537

4638
DependencyScanningWorker::~DependencyScanningWorker() = default;
@@ -102,7 +94,18 @@ bool DependencyScanningWorker::scanDependencies(
10294
StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
10395
DependencyConsumer &Consumer, DependencyActionController &Controller,
10496
DiagnosticConsumer &DC,
105-
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS) {
97+
IntrusiveRefCntPtr<llvm::vfs::FileSystem> OverlayFS) {
98+
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = DepFS;
99+
if (OverlayFS) {
100+
#ifndef NDEBUG
101+
bool SawDepFS = false;
102+
OverlayFS->visit(
103+
[&](llvm::vfs::FileSystem &VFS) { SawDepFS |= &VFS == DepFS.get(); });
104+
assert(SawDepFS && "OverlayFS not based on DepFS");
105+
#endif
106+
FS = std::move(OverlayFS);
107+
}
108+
106109
DignosticsEngineWithDiagOpts DiagEngineWithCmdAndOpts(CommandLine, FS, DC);
107110
DependencyScanningAction Action(Service, WorkingDirectory, Consumer,
108111
Controller, DepFS);
@@ -158,13 +161,13 @@ bool DependencyScanningWorker::computeDependencies(
158161
DiagnosticConsumer &DC, std::optional<llvm::MemoryBufferRef> TUBuffer) {
159162
if (TUBuffer) {
160163
auto [FinalFS, FinalCommandLine] = initVFSForTUBufferScanning(
161-
BaseFS, CommandLine, WorkingDirectory, *TUBuffer);
164+
DepFS, CommandLine, WorkingDirectory, *TUBuffer);
162165
return scanDependencies(WorkingDirectory, FinalCommandLine, Consumer,
163166
Controller, DC, FinalFS);
164167
} else {
165-
BaseFS->setCurrentWorkingDirectory(WorkingDirectory);
168+
DepFS->setCurrentWorkingDirectory(WorkingDirectory);
166169
return scanDependencies(WorkingDirectory, CommandLine, Consumer, Controller,
167-
DC, BaseFS);
170+
DC);
168171
}
169172
}
170173

0 commit comments

Comments
 (0)