[llvm] [clang] [clang][DependencyScanner] Remove unused -ivfsoverlay files (PR #73734)

2024-01-30 Thread Jan Svoboda via cfe-commits

https://github.com/jansvoboda11 edited 
https://github.com/llvm/llvm-project/pull/73734
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang] [clang][DependencyScanner] Remove unused -ivfsoverlay files (PR #73734)

2024-01-30 Thread Jan Svoboda via cfe-commits


@@ -576,6 +576,12 @@ class HeaderSearch {
   /// Note: implicit module maps don't contribute to entry usage.
   std::vector computeUserEntryUsage() const;
 
+  /// Determine which HeaderSearchOptions::VFSOverlayFiles have been
+  /// successfully used so far and mark their index with 'true' in the 
resulting
+  /// bit vector.
+  /// Note: implicit module maps don't contribute to entry usage.

jansvoboda11 wrote:

This might be a leftover from the previous approach.

https://github.com/llvm/llvm-project/pull/73734
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang] [clang][DependencyScanner] Remove unused -ivfsoverlay files (PR #73734)

2024-01-29 Thread Michael Spencer via cfe-commits

https://github.com/Bigcheese updated 
https://github.com/llvm/llvm-project/pull/73734

>From 0559ec44d2d3c39292bae6d6431dde9626ac755e Mon Sep 17 00:00:00 2001
From: Michael Spencer 
Date: Fri, 24 Feb 2023 17:18:51 -0800
Subject: [PATCH 1/2] [clang][DepScan] Remove unused -ivfsoverlay files

`-ivfsoverlay` files are unused when building most modules. Enable
removing them by,
* adding a way to visit the filesystem tree with extensible RTTI to
  access each `RedirectingFileSystem`.
* Adding tracking to `RedirectingFileSystem` to record when it
  actually redirects a file access.
* Storing this information in each PCM.

Usage tracking is only enabled when iterating over the source manager
and affecting modulemaps. Here each path is stated to cause an access.
During scanning these stats all hit the cache.
---
 .../Basic/DiagnosticSerializationKinds.td |   3 +
 clang/include/clang/Basic/FileManager.h   |   4 +
 clang/include/clang/Lex/HeaderSearch.h|   6 +
 clang/include/clang/Lex/HeaderSearchOptions.h |   6 +-
 .../include/clang/Serialization/ASTBitCodes.h |   3 +
 clang/include/clang/Serialization/ASTReader.h |  16 +-
 .../include/clang/Serialization/ModuleFile.h  |   3 +
 .../DependencyScanningFilesystem.h|   6 +-
 .../DependencyScanningService.h   |  11 +-
 clang/lib/Basic/FileManager.cpp   |   7 +
 clang/lib/Frontend/CompilerInvocation.cpp |   1 +
 clang/lib/Lex/HeaderSearch.cpp|  16 ++
 clang/lib/Serialization/ASTReader.cpp |  41 ++--
 clang/lib/Serialization/ASTWriter.cpp |  41 +++-
 .../DependencyScanningFilesystem.cpp  |   6 +-
 .../DependencyScanningWorker.cpp  |  86 ++--
 .../DependencyScanning/ModuleDepCollector.cpp |  74 +--
 .../ClangScanDeps/optimize-vfs-edgecases.m|  84 
 clang/test/ClangScanDeps/optimize-vfs-leak.m  | 105 ++
 clang/test/ClangScanDeps/optimize-vfs-pch.m   | 129 
 clang/test/ClangScanDeps/optimize-vfs.m   | 193 ++
 clang/tools/clang-scan-deps/ClangScanDeps.cpp |   1 +
 llvm/include/llvm/Support/VirtualFileSystem.h |  55 -
 llvm/lib/Support/VirtualFileSystem.cpp|  26 +++
 .../Support/VirtualFileSystemTest.cpp |  86 
 25 files changed, 932 insertions(+), 77 deletions(-)
 create mode 100644 clang/test/ClangScanDeps/optimize-vfs-edgecases.m
 create mode 100644 clang/test/ClangScanDeps/optimize-vfs-leak.m
 create mode 100644 clang/test/ClangScanDeps/optimize-vfs-pch.m
 create mode 100644 clang/test/ClangScanDeps/optimize-vfs.m

diff --git a/clang/include/clang/Basic/DiagnosticSerializationKinds.td 
b/clang/include/clang/Basic/DiagnosticSerializationKinds.td
index 11c706ebf84b54..4c4659ed517e0a 100644
--- a/clang/include/clang/Basic/DiagnosticSerializationKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSerializationKinds.td
@@ -44,6 +44,9 @@ def err_pch_diagopt_mismatch : Error<"%0 is currently 
enabled, but was not in "
   "the PCH file">;
 def err_pch_modulecache_mismatch : Error<"PCH was compiled with module cache "
   "path '%0', but the path is currently '%1'">;
+def err_pch_vfsoverlay_mismatch : Error<"PCH was compiled with different VFS 
overlay files than are currently in use">;
+def note_pch_vfsoverlay_files : Note<"%select{PCH|current translation unit}0 
has the following VFS overlays:\n%1">;
+def note_pch_vfsoverlay_empty : Note<"%select{PCH|current translation unit}0 
has no VFS overlays">;
 
 def err_pch_version_too_old : Error<
 "PCH file uses an older PCH format that is no longer supported">;
diff --git a/clang/include/clang/Basic/FileManager.h 
b/clang/include/clang/Basic/FileManager.h
index 56cb093dd8c376..997c17a0ffcfcc 100644
--- a/clang/include/clang/Basic/FileManager.h
+++ b/clang/include/clang/Basic/FileManager.h
@@ -248,6 +248,10 @@ class FileManager : public RefCountedBase {
 return FS;
   }
 
+  /// Enable or disable tracking of VFS usage. Used to not track full header
+  /// search and implicit modulemap lookup.
+  void trackVFSUsage(bool Active);
+
   void setVirtualFileSystem(IntrusiveRefCntPtr FS) {
 this->FS = std::move(FS);
   }
diff --git a/clang/include/clang/Lex/HeaderSearch.h 
b/clang/include/clang/Lex/HeaderSearch.h
index a2c33842924b10..49e1a4a124b55d 100644
--- a/clang/include/clang/Lex/HeaderSearch.h
+++ b/clang/include/clang/Lex/HeaderSearch.h
@@ -576,6 +576,12 @@ class HeaderSearch {
   /// Note: implicit module maps don't contribute to entry usage.
   std::vector computeUserEntryUsage() const;
 
+  /// Determine which HeaderSearchOptions::VFSOverlayFiles have been
+  /// successfully used so far and mark their index with 'true' in the 
resulting
+  /// bit vector.
+  /// Note: implicit module maps don't contribute to entry usage.
+  std::vector computeVFSUsageAndClear() const;
+
   /// This method returns a HeaderMap for the specified
   /// FileEntry, uniquing them through the 'HeaderMaps' datastructure.
   const HeaderMap *CreateHeader

[llvm] [clang] [clang][DependencyScanner] Remove unused -ivfsoverlay files (PR #73734)

2024-01-29 Thread Jan Svoboda via cfe-commits

https://github.com/jansvoboda11 edited 
https://github.com/llvm/llvm-project/pull/73734
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang] [clang][DependencyScanner] Remove unused -ivfsoverlay files (PR #73734)

2024-01-29 Thread Jan Svoboda via cfe-commits


@@ -141,6 +141,22 @@ std::vector HeaderSearch::computeUserEntryUsage() 
const {
   return UserEntryUsage;
 }
 
+std::vector HeaderSearch::computeVFSUsageAndClear() const {

jansvoboda11 wrote:

Nit: I'm a bit confused that the function that actually does the work (the 
logic itself, constructing offset tables, piping relevant files into 
`FileManager`) is called `collectNonAffectingInputFiles()`, while this function 
(that just traverses the VFS tree and collects bits) is called 
`computeVFSUsageAndClear()`. I'd expect it to be the other way around.

https://github.com/llvm/llvm-project/pull/73734
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang] [clang][DependencyScanner] Remove unused -ivfsoverlay files (PR #73734)

2024-01-29 Thread Jan Svoboda via cfe-commits


@@ -141,6 +141,22 @@ std::vector HeaderSearch::computeUserEntryUsage() 
const {
   return UserEntryUsage;
 }
 
+std::vector HeaderSearch::computeVFSUsageAndClear() const {
+  std::vector VFSUsage;
+  llvm::vfs::FileSystem &RootFS = FileMgr.getVirtualFileSystem();
+  // TODO: This only works if the `RedirectingFileSystem`s were all created by
+  //   `createVFSFromOverlayFiles`.
+  RootFS.visit([&](llvm::vfs::FileSystem &FS) {
+if (auto *RFS = dyn_cast(&FS)) {
+  VFSUsage.push_back(RFS->hasBeenUsed());
+  RFS->clearHasBeenUsed();
+}
+  });
+  // VFS visit order is the opposite of VFSOverlayFiles order.
+  std::reverse(VFSUsage.begin(), VFSUsage.end());
+  return VFSUsage;

jansvoboda11 wrote:

Might be worth asserting that size of `VFSUsage` is the same as the size of 
`HeaderSearchOptions::VFSOverlayFiles`.

https://github.com/llvm/llvm-project/pull/73734
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang] [clang][DependencyScanner] Remove unused -ivfsoverlay files (PR #73734)

2024-01-29 Thread Jan Svoboda via cfe-commits


@@ -4687,6 +4699,15 @@ void ASTWriter::collectNonAffectingInputFiles() {
   NonAffectingFileIDAdjustments.push_back(FileIDAdjustment);
   NonAffectingOffsetAdjustments.push_back(OffsetAdjustment);
 
+  const bool IncludeVFSUsage =
+  PP->getHeaderSearchInfo().getHeaderSearchOpts().ModulesIncludeVFSUsage;
+  FileManager &FileMgr = PP->getFileManager();
+  FileMgr.trackVFSUsage(true);

jansvoboda11 wrote:

The scope of tracking is fairly long. Instead of intertwining it with the logic 
for finding affecting files and constructing the offset adjustment table, I 
think it would be clearer to have a separate loop at the end of this function:

```c++
if (IncludeVFSUsage)
  for (unsigned I = 1; I != N; ++I)
if (IsSLocAffecting[I]) {
  SrcMgr::FileInfo File = /*...*/;
  FileMgr.getVirtualFileSystem().exists(
File.getContentCache().OrigEntry->getNameAsRequested());
}
```

https://github.com/llvm/llvm-project/pull/73734
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang] [clang][DependencyScanner] Remove unused -ivfsoverlay files (PR #73734)

2024-01-29 Thread Jan Svoboda via cfe-commits


@@ -9312,6 +9312,19 @@ SourceRange ASTReader::ReadSourceRange(ModuleFile &F, 
const RecordData &Record,
   return SourceRange(beg, end);
 }
 
+llvm::BitVector ASTReader::ReadBitVector(const RecordData &Record,
+ const StringRef Blob) {
+  llvm::BitVector Ret;

jansvoboda11 wrote:

Can we drop this and turn the assignment to `Ret` below into a declaration?

https://github.com/llvm/llvm-project/pull/73734
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang] [clang][DependencyScanner] Remove unused -ivfsoverlay files (PR #73734)

2024-01-29 Thread Jan Svoboda via cfe-commits

https://github.com/jansvoboda11 commented:

This looks pretty good! I have just a couple of minor comments.

https://github.com/llvm/llvm-project/pull/73734
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang] [clang][DependencyScanner] Remove unused -ivfsoverlay files (PR #73734)

2024-01-29 Thread Jan Svoboda via cfe-commits

https://github.com/jansvoboda11 edited 
https://github.com/llvm/llvm-project/pull/73734
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang] [clang][DependencyScanner] Remove unused -ivfsoverlay files (PR #73734)

2024-01-25 Thread Michael Spencer via cfe-commits

Bigcheese wrote:

I've updated the patch to use the alternative implementation Jan suggested.

https://github.com/llvm/llvm-project/pull/73734
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang] [clang][DependencyScanner] Remove unused -ivfsoverlay files (PR #73734)

2023-11-29 Thread Jan Svoboda via cfe-commits

jansvoboda11 wrote:

I'm not thrilled by the chosen implementation strategy. Disabling tracking 
during parts of header search does not sound obviously correct to me. Module 
map search can have subtle side-effects, and I wouldn't be suprised if this 
feature was affected by one. That said, I haven't been able to come up with a 
case where this would yield incorrect results.

An alternative implementation I'd be more confident in would be to grab the set 
of files we know affect the compilation (built on top of 
`ASTWriter::collectNonAffectingInputFiles()`) and call 
`FileManager::getOptionalFileRef()` with their 
`FileEntryRef::getNameAsRequested()`.

https://github.com/llvm/llvm-project/pull/73734
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang] [clang][DependencyScanner] Remove unused -ivfsoverlay files (PR #73734)

2023-11-29 Thread Jan Svoboda via cfe-commits

jansvoboda11 wrote:

We set `RedirectingFileSystem::HasBeenUsed` to `true` while implicitly 
compiling one module, but then hand off the same VFS object to implicit compile 
of another module. This will cause all modules discovered later to incorrectly 
inherit that bit from previous modules. This will also introduce 
non-determinism based on the TU that reached a module first (and which modules 
it imported on the way). Here's a test case:
```
// This test checks that VFS usage doesn't leak between modules.

// RUN: rm -rf %t && split-file %s %t
// RUN: sed -e "s|DIR|%/t|g" %t/build/cdb.json.in > %t/build/cdb.json
// RUN: sed -e "s|DIR|%/t|g" %t/build/vfs.yaml.in > %t/build/vfs.yaml
// RUN: clang-scan-deps -compilation-database %t/build/cdb.json \
// RUN:   -format experimental-full --optimize-args=vfs > %t/deps.json
// RUN: cat %t/deps.json | sed 's:\?:/:g' | FileCheck %s -DPREFIX=%/t

// CHECK:  {
// CHECK-NEXT:   "modules": [
// CHECK-NEXT: {
// CHECK-NEXT:   "clang-module-deps": [
// CHECK-NEXT: {
// CHECK-NEXT:   "context-hash": "{{.*}}",
// CHECK-NEXT:   "module-name": "B"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT:   "context-hash": "{{.*}}",
// CHECK-NEXT:   "module-name": "C"
// CHECK-NEXT: }
// CHECK-NEXT:   ],
// CHECK-NEXT:   "clang-modulemap-file": 
"[[PREFIX]]/moduleA/module.modulemap",
// CHECK-NEXT:   "command-line": [
// Module A needs the VFS overlay because its dependency, module B, needs it.
// CHECK:  "-ivfsoverlay"
// CHECK-NEXT: "[[PREFIX]]/build/vfs.yaml"
// CHECK:],
// CHECK-NEXT:   "context-hash": "{{.*}}",
// CHECK-NEXT:   "file-deps": [
// CHECK:],
// CHECK-NEXT:   "name": "A"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT:   "clang-module-deps": [],
// CHECK-NEXT:   "clang-modulemap-file": 
"[[PREFIX]]/moduleB/module.modulemap",
// CHECK-NEXT:   "command-line": [
// Module B needs the VFS overlay because it provides the header referred to by 
the module map.
// CHECK:  "-ivfsoverlay"
// CHECK-NEXT: "[[PREFIX]]/build/vfs.yaml"
// CHECK:],
// CHECK-NEXT:   "context-hash": "{{.*}}",
// CHECK-NEXT:   "file-deps": [
// CHECK:],
// CHECK-NEXT:   "name": "B"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT:   "clang-module-deps": [],
// CHECK-NEXT:   "clang-modulemap-file": 
"[[PREFIX]]/moduleC/module.modulemap",
// CHECK-NEXT:   "command-line": [
// Module C doesn't need the VFS overlay.
// CHECK-NOT:  "-ivfsoverlay"
// CHECK:],
// CHECK-NEXT:   "context-hash": "{{.*}}",
// CHECK-NEXT:   "file-deps": [
// CHECK:],
// CHECK-NEXT:   "name": "C"
// CHECK-NEXT: }
// CHECK-NEXT:   ],
// CHECK-NEXT:   "translation-units": [
// CHECK:]
// CHECK:  }

//--- build/cdb.json.in
[{
  "directory": "DIR",
  "command": "clang -c DIR/tu.m -I DIR/moduleA -I DIR/moduleB -I DIR/moduleC 
-fmodules -fmodules-cache-path=DIR/cache -fimplicit-module-maps -ivfsoverlay 
DIR/build/vfs.yaml",
  "file": "DIR/tu.m"
}]

//--- build/vfs.yaml.in
{
  "version": 0,
  "case-sensitive": "false",
  "roots": [
{
  "contents": [
{
  "external-contents": "DIR/build/B.h",
  "name": "B.h",
  "type": "file"
}
  ],
  "name": "DIR/moduleB",
  "type": "directory"
}
  ]
}

//--- tu.m
@import A;

//--- moduleA/module.modulemap
module A { header "A.h" }
//--- moduleA/A.h
@import B;
@import C;

//--- moduleB/module.modulemap
module B { header "B.h" }
//--- build/B.h

//--- moduleC/module.modulemap
module C { header "C.h" }
//--- moduleC/C.h
```

https://github.com/llvm/llvm-project/pull/73734
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang] [clang][DependencyScanner] Remove unused -ivfsoverlay files (PR #73734)

2023-11-29 Thread Michael Spencer via cfe-commits


@@ -142,6 +142,21 @@ std::vector HeaderSearch::computeUserEntryUsage() 
const {
   return UserEntryUsage;
 }
 
+std::vector HeaderSearch::computeVFSUsage() const {
+  std::vector VFSUsage;
+  llvm::vfs::FileSystem &RootFS = FileMgr.getVirtualFileSystem();
+  // TODO: This only works if the `RedirectingFileSystem`s were all created by

Bigcheese wrote:

We could set a bit, and then just skip over VFSs without the bit. That would 
work even if people manually pass in a VFS with an extra 
`RedirectingFileSystem`, and we have a check later that would fire if 
`createVFSFromOverlayFiles ` wasn't used at all.

https://github.com/llvm/llvm-project/pull/73734
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang] [clang][DependencyScanner] Remove unused -ivfsoverlay files (PR #73734)

2023-11-29 Thread Michael Spencer via cfe-commits


@@ -498,11 +518,18 @@ class NamedNodeOrError {
 } // namespace detail
 
 /// An in-memory file system.
-class InMemoryFileSystem : public FileSystem {
+class InMemoryFileSystem : public RTTIExtends {
   std::unique_ptr Root;
   std::string WorkingDirectory;
   bool UseNormalizedPaths = true;
 
+public:
+  static const char ID;
+  using GetFileContentsCallback =

Bigcheese wrote:

Ah, looks like it snuck in while rebasing.

https://github.com/llvm/llvm-project/pull/73734
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang] [clang][DependencyScanner] Remove unused -ivfsoverlay files (PR #73734)

2023-11-29 Thread Michael Spencer via cfe-commits

Bigcheese wrote:

> It's odd to me that tracking is enabled by default. I would have expected 
> tracking be off by default and enabled explicitly for scanning. Similarly, in 
> the modulemap case it could save-and-restore rather than enable the tracking 
> if it was previously off.

It has to be on by default because of PCH. You never know if a PCM will be used 
for scanning.

https://github.com/llvm/llvm-project/pull/73734
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang] [clang][DependencyScanner] Remove unused -ivfsoverlay files (PR #73734)

2023-11-28 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-llvm-support

Author: Michael Spencer (Bigcheese)


Changes

`-ivfsoverlay` files are unused when building most modules. Enable
removing them by,
* adding a way to visit the filesystem tree with extensible RTTI to
  access each `RedirectingFileSystem`.
* Adding tracking to `RedirectingFileSystem` to record when it
  actually redirects a file access.
* Storing this information in each PCM.

Usage tracking is disabled during implicit modulemap search as this
ends up touching a lot of files that aren't actually used. The used
files are later touched by other parts of Clang so relevant VFS
overlays get marked as used.

---

Patch is 34.79 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/73734.diff


18 Files Affected:

- (modified) clang/include/clang/Basic/FileManager.h (+4) 
- (modified) clang/include/clang/Lex/HeaderSearch.h (+6) 
- (modified) clang/include/clang/Serialization/ASTBitCodes.h (+3) 
- (modified) clang/include/clang/Serialization/ModuleFile.h (+3) 
- (modified) 
clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h 
(+5-1) 
- (modified) 
clang/include/clang/Tooling/DependencyScanning/DependencyScanningService.h 
(+4-1) 
- (modified) clang/lib/Basic/FileManager.cpp (+7) 
- (modified) clang/lib/Frontend/CompilerInvocation.cpp (+1) 
- (modified) clang/lib/Lex/HeaderSearch.cpp (+20) 
- (modified) clang/lib/Serialization/ASTReader.cpp (+14-1) 
- (modified) clang/lib/Serialization/ASTWriter.cpp (+18-6) 
- (modified) 
clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp (+5-1) 
- (modified) clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp 
(+53-21) 
- (added) clang/test/ClangScanDeps/optimize-vfs.m (+193) 
- (modified) clang/tools/clang-scan-deps/ClangScanDeps.cpp (+1) 
- (modified) llvm/include/llvm/Support/VirtualFileSystem.h (+49-8) 
- (modified) llvm/lib/Support/VirtualFileSystem.cpp (+26) 
- (modified) llvm/unittests/Support/VirtualFileSystemTest.cpp (+84) 


``diff
diff --git a/clang/include/clang/Basic/FileManager.h 
b/clang/include/clang/Basic/FileManager.h
index 56cb093dd8c376f..997c17a0ffcfcce 100644
--- a/clang/include/clang/Basic/FileManager.h
+++ b/clang/include/clang/Basic/FileManager.h
@@ -248,6 +248,10 @@ class FileManager : public RefCountedBase {
 return FS;
   }
 
+  /// Enable or disable tracking of VFS usage. Used to not track full header
+  /// search and implicit modulemap lookup.
+  void trackVFSUsage(bool Active);
+
   void setVirtualFileSystem(IntrusiveRefCntPtr FS) {
 this->FS = std::move(FS);
   }
diff --git a/clang/include/clang/Lex/HeaderSearch.h 
b/clang/include/clang/Lex/HeaderSearch.h
index a100598c80155fa..7c21796b0460238 100644
--- a/clang/include/clang/Lex/HeaderSearch.h
+++ b/clang/include/clang/Lex/HeaderSearch.h
@@ -579,6 +579,12 @@ class HeaderSearch {
   /// Note: implicit module maps don't contribute to entry usage.
   std::vector computeUserEntryUsage() const;
 
+  /// Determine which HeaderSearchOptions::VFSOverlayFiles have been
+  /// successfully used so far and mark their index with 'true' in the 
resulting
+  /// bit vector.
+  /// Note: implicit module maps don't contribute to entry usage.
+  std::vector computeVFSUsage() const;
+
   /// This method returns a HeaderMap for the specified
   /// FileEntry, uniquing them through the 'HeaderMaps' datastructure.
   const HeaderMap *CreateHeaderMap(FileEntryRef FE);
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h 
b/clang/include/clang/Serialization/ASTBitCodes.h
index fdd64f2abbe9375..f4abfe6f560664f 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -405,6 +405,9 @@ enum UnhashedControlBlockRecordTypes {
 
   /// Record code for the indices of used header search entries.
   HEADER_SEARCH_ENTRY_USAGE,
+
+  /// Record code for the indices of used VFSs.
+  VFS_USAGE,
 };
 
 /// Record code for extension blocks.
diff --git a/clang/include/clang/Serialization/ModuleFile.h 
b/clang/include/clang/Serialization/ModuleFile.h
index 48be8676cc26a4c..a2d49507a579427 100644
--- a/clang/include/clang/Serialization/ModuleFile.h
+++ b/clang/include/clang/Serialization/ModuleFile.h
@@ -189,6 +189,9 @@ class ModuleFile {
   /// The bit vector denoting usage of each header search entry (true = used).
   llvm::BitVector SearchPathUsage;
 
+  /// The bit vector denoting usage of each VFS entry (true = used).
+  llvm::BitVector VFSUsage;
+
   /// Whether this module has been directly imported by the
   /// user.
   bool DirectlyImported = false;
diff --git 
a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h 
b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h
index 9a2aea5d6efa170..846fdc7253977f9 100644
--- 
a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h
+++ 
b/clang/include/clang/Tooling/DependencyScanning/Dep