[clang] [C++20] [Modules] Introduce thin BMI (PR #71622)

Chuanqi Xu via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 7 18:18:06 PST 2023


https://github.com/ChuanqiXu9 created https://github.com/llvm/llvm-project/pull/71622

Close https://github.com/llvm/llvm-project/issues/71034

This patch introduces thin BMI, which doesn't contain the definitions of functions and variables if its definitions won't contribute to the ABI.

Testing is a big part of the patch. We want to make sure the thin BMI contains the same behavior with the existing and relatively stable fatBMI. This is pretty helpful for further reduction.

For user interfeaces, this patch introduces `-fthinBMI-output=` arguments to specify the position of thin BMI. This should be used when compiling a single module unit.

The design is helpful to use thin BMI in two phase compilations too. With thin BMI, In two phase compilations, we'll generate 2 BMIs, one thin BMI for being used by consumers, one fat BMI for compiling itself to object files. Maybe it sounds confusing to have 2 BMIs for one module unit. But only the thin BMI will be the BMI we're talking about generally and the fat BMI is only visible by the module unit itself.

With one phase compilation, we may find the behavior of `-fthinBMI-output=` is pretty similar with `-fmodule-output=`, except one generating thin BMI and the other generating fat BMI. The design here is based on 2 things:
(1) The serialization of C++ is pretty complex. We can't be sure we're handling every detail correctly in the every beginning.
(2) The fat BMI is relatively widely used and relatively stable. So it looks not good to replace the fat BMI immediately with thin BMI.

But, of course, in the end of the day, we want the consumers to use the thin BMI only. When that day comes, the `-fmodule-output=` will be an alias to `-fthinBMI-output=`.

Another design choice is to reuse `-fmodule-output=` and introduce a flag `-femit-thin-BMI`. Then `-femit-thin-BMI -fmodule-output=` will have the same effect with `-fthinBMI-output=` now.
The flag `-femit-thin-BMI` should be opt-in now and opt-off later and finally deprecated.

The roadmap for thin BMI in my mind is:

(1) In clang18, release thin BMI and mark it as experimental. Also encourage users and build systems to try this new mode. (2) In clang19 or clang20 (based on the issue feedbacks), remove the experimental mark for thin BMI and mark fat BMI as deprecated to be used by consumers.
(3) In clang21 or clang22, error out if we found the users are trying to import a fat BMI.

CC: @mathstuf 

>From 839d38d96d2275dbc0a9aa9fae3427720a6d3344 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu <yedeng.yd at linux.alibaba.com>
Date: Wed, 8 Nov 2023 09:55:07 +0800
Subject: [PATCH] [C++20] [Modules] Introduce thin BMI

Close https://github.com/llvm/llvm-project/issues/71034

This patch introduces thin BMI, which doesn't contain the definitions of
functions and variables if its definitions won't contribute to the ABI.

Testing is a big part of the patch. We want to make sure the thin BMI
contains the same behavior with the existing and relatively stable
fatBMI. This is pretty helpful for further reduction.

For user interfeaces, this patch introduces `-fthinBMI-output=`
arguments to specify the position of thin BMI. This should be used when
compiling a single module unit.

The design is helpful to use thin BMI in two phase compilations too.
With thin BMI, In two phase compilations, we'll generate 2 BMIs, one
thin BMI for being used by consumers, one fat BMI for compiling itself
to object files. Maybe it sounds confusing to have 2 BMIs for one module
unit. But only the thin BMI will be the BMI we're talking about
generally and the fat BMI is only visible by the module unit itself.

With one phase compilation, we may find the behavior of
`-fthinBMI-output=` is pretty similar with `-fmodule-output=`, except
one generating thin BMI and the other generating fat BMI. The design
here is based on 2 things:
(1) The serialization of C++ is pretty complex. We can't be sure we're handling
every detail correctly in the every beginning.
(2) The fat BMI is relatively widely used and relatively stable.
So it looks not good to replace the fat BMI immediately with thin BMI.

But, of course, in the end of the day, we want the consumers to use the
thin BMI only. When that day comes, the `-fmodule-output=` will be an alias to
`-fthinBMI-output=`.

Another design choice is to reuse `-fmodule-output=` and introduce a flag
`-femit-thin-BMI`. Then `-femit-thin-BMI -fmodule-output=` will have the same effect
with `-fthinBMI-output=` now.
The flag `-femit-thin-BMI` should be opt-in now and opt-off later
and finally deprecated.

The roadmap for thin BMI in my mind is:

(1) In clang18, release thin BMI and mark it as experimental. Also
encourage users and build systems to try this new mode.
(2) In clang19 or clang20 (based on the issue feedbacks), remove the
experimental mark for thin BMI and mark fat BMI as deprecated to be
used by consumers.
(3) In clang21 or clang22, error out if we found the users are trying to
import a fat BMI.
---
 .../clang/Basic/DiagnosticDriverKinds.td      |  2 +
 clang/include/clang/Driver/Options.td         |  9 +++-
 .../include/clang/Frontend/FrontendActions.h  | 18 ++++++-
 .../include/clang/Frontend/FrontendOptions.h  |  9 +++-
 clang/include/clang/Serialization/ASTWriter.h | 31 ++++++++++-
 clang/lib/Driver/Driver.cpp                   |  7 +++
 clang/lib/Driver/ToolChains/Clang.cpp         |  2 +
 clang/lib/Frontend/CompilerInvocation.cpp     |  2 +
 clang/lib/Frontend/FrontendActions.cpp        | 52 ++++++++++++++++--
 .../ExecuteCompilerInvocation.cpp             |  2 +
 clang/lib/Serialization/ASTWriter.cpp         | 32 ++++++-----
 clang/lib/Serialization/ASTWriterDecl.cpp     | 53 ++++++++++++++++---
 clang/lib/Serialization/GeneratePCH.cpp       | 36 ++++++++++++-
 clang/test/CXX/basic/basic.link/p10-ex2.cpp   |  3 +-
 .../p4-friend-in-reachable-class.cpp          |  6 ++-
 clang/test/Driver/thinBMI-output.cppm         | 29 ++++++++++
 .../test/Modules/InheritDefaultArguments.cppm |  3 ++
 clang/test/Modules/Reachability-Private.cpp   | 10 ++++
 .../Modules/Reachability-func-default-arg.cpp |  3 ++
 clang/test/Modules/Reachability-func-ret.cpp  |  3 ++
 .../Reachability-template-default-arg.cpp     |  3 ++
 .../Reachability-template-instantiation.cpp   |  4 ++
 .../Modules/Reachability-using-templates.cpp  |  3 ++
 clang/test/Modules/Reachability-using.cpp     |  3 ++
 clang/test/Modules/concept.cppm               |  4 ++
 clang/test/Modules/concept_differ.cppm        |  5 ++
 clang/test/Modules/ctor.arg.dep.cppm          |  4 ++
 clang/test/Modules/cxx20-10-1-ex1.cpp         | 13 +++++
 clang/test/Modules/cxx20-10-1-ex2.cpp         | 36 ++++++++++---
 clang/test/Modules/cxx20-10-2-ex2.cpp         | 12 +++++
 clang/test/Modules/cxx20-10-2-ex5.cpp         | 12 +++++
 clang/test/Modules/cxx20-10-3-ex1.cpp         | 14 +++++
 clang/test/Modules/cxx20-10-3-ex2.cpp         | 10 ++++
 clang/test/Modules/cxx20-10-5-ex1.cpp         | 12 +++++
 .../Modules/cxx20-import-diagnostics-a.cpp    | 39 ++++++++++++++
 .../Modules/cxx20-import-diagnostics-b.cpp    | 25 +++++++++
 .../Modules/cxx20-module-file-info-macros.cpp |  3 ++
 clang/test/Modules/deduction-guide.cppm       |  3 ++
 clang/test/Modules/deduction-guide2.cppm      |  3 ++
 clang/test/Modules/deduction-guide3.cppm      |  3 ++
 clang/test/Modules/derived_class.cpp          |  3 ++
 ...duplicated-module-file-eq-module-name.cppm |  4 ++
 clang/test/Modules/enum-class.cppm            |  3 ++
 .../explicitly-specialized-template.cpp       |  3 ++
 .../test/Modules/export-language-linkage.cppm |  5 ++
 clang/test/Modules/ftime-trace.cppm           |  9 ++++
 .../inconsistent-deduction-guide-linkage.cppm |  6 +++
 clang/test/Modules/inconsistent-export.cppm   | 13 +++++
 clang/test/Modules/inherited_arg.cppm         | 11 ++++
 .../Modules/instantiation-argdep-lookup.cppm  |  3 ++
 clang/test/Modules/lambdas.cppm               | 15 ++++++
 .../Modules/merge-concepts-cxx-modules.cpp    | 12 +++++
 .../Modules/merge-constrained-friends.cpp     |  3 ++
 clang/test/Modules/merge-lambdas.cppm         |  4 ++
 .../Modules/merge-requires-with-lambdas.cppm  | 19 +++++++
 .../merge-var-template-spec-cxx-modules.cppm  |  5 ++
 clang/test/Modules/mismatch-diagnostics.cpp   | 11 ++++
 .../module-init-duplicated-import.cppm        | 11 ++++
 clang/test/Modules/named-modules-adl-2.cppm   |  4 ++
 clang/test/Modules/named-modules-adl-3.cppm   | 17 ++++++
 clang/test/Modules/named-modules-adl.cppm     |  3 ++
 .../Modules/no-duplicate-codegen-in-GMF.cppm  |  8 +++
 clang/test/Modules/pair-unambiguous-ctor.cppm |  9 ++++
 .../test/Modules/partial_specialization.cppm  |  3 ++
 .../test/Modules/placement-new-reachable.cpp  |  3 ++
 clang/test/Modules/polluted-operator.cppm     |  3 ++
 clang/test/Modules/pr54457.cppm               |  3 ++
 clang/test/Modules/pr56916.cppm               | 12 +++++
 clang/test/Modules/pr58532.cppm               |  6 +++
 clang/test/Modules/pr58716.cppm               |  2 +-
 clang/test/Modules/pr59719.cppm               |  3 ++
 clang/test/Modules/pr59780.cppm               |  8 +++
 clang/test/Modules/pr59999.cppm               | 13 +++++
 clang/test/Modules/pr60036.cppm               | 14 +++++
 clang/test/Modules/pr60085.cppm               | 17 ++++++
 clang/test/Modules/pr60275.cppm               |  7 ++-
 clang/test/Modules/pr60486.cppm               |  3 ++
 clang/test/Modules/pr60693.cppm               |  4 ++
 clang/test/Modules/pr60775.cppm               | 13 +++++
 clang/test/Modules/pr60890.cppm               |  6 +++
 clang/test/Modules/pr61065.cppm               | 13 +++++
 clang/test/Modules/pr61065_2.cppm             | 15 ++++++
 clang/test/Modules/pr61067.cppm               | 14 +++++
 clang/test/Modules/pr61317.cppm               |  9 ++++
 clang/test/Modules/pr61783.cppm               |  8 +++
 clang/test/Modules/pr61892.cppm               | 40 +++++++-------
 clang/test/Modules/pr62158.cppm               |  9 ++++
 clang/test/Modules/pr62359.cppm               | 16 ++++++
 clang/test/Modules/pr62589.cppm               |  3 ++
 clang/test/Modules/pr62705.cppm               |  8 +++
 clang/test/Modules/pr62796.cppm               |  4 ++
 clang/test/Modules/pr62943.cppm               | 12 +++++
 clang/test/Modules/pr63544.cppm               | 12 +++++
 clang/test/Modules/pr63595.cppm               | 10 ++++
 clang/test/Modules/pr67627.cppm               |  4 ++
 clang/test/Modules/pr67893.cppm               | 12 +++++
 clang/test/Modules/predefined.cpp             |  3 ++
 clang/test/Modules/preferred_name.cppm        | 10 ++++
 clang/test/Modules/redefinition-merges.cppm   |  6 +++
 .../redundant-template-default-arg.cpp        |  3 ++
 .../redundant-template-default-arg2.cpp       |  3 ++
 .../redundant-template-default-arg3.cpp       |  3 ++
 clang/test/Modules/search-partitions.cpp      | 16 ++++++
 ...unction-definition-for-template-class.cppm | 12 +++++
 .../template-function-specialization.cpp      |  5 +-
 clang/test/Modules/template-lambdas.cppm      | 15 ++++++
 clang/test/Modules/template-pack.cppm         |  3 ++
 .../Modules/template_default_argument.cpp     |  3 ++
 clang/unittests/Sema/SemaNoloadLookupTest.cpp |  9 ++--
 .../Serialization/ForceCheckFileInputTest.cpp | 10 ++--
 .../Serialization/NoCommentsTest.cpp          |  9 ++--
 .../Serialization/VarDeclConstantInitTest.cpp | 13 +++--
 112 files changed, 1053 insertions(+), 83 deletions(-)
 create mode 100644 clang/test/Driver/thinBMI-output.cppm

diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 676f1a62b49dd0d..aad67a9f4c7da01 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -158,6 +158,8 @@ def err_drv_invalid_output_with_multiple_archs : Error<
 def err_drv_no_input_files : Error<"no input files">;
 def err_drv_output_argument_with_multiple_files : Error<
   "cannot specify -o when generating multiple output files">;
+def err_drv_thin_bmi_output_argument_with_multiple_files : Error <
+  "cannot specify -fthinBMI-output when generating multiple module files">;
 def err_drv_out_file_argument_with_multiple_sources : Error<
   "cannot specify '%0%1' when compiling multiple source files">;
 def err_no_external_assembler : Error<
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 36052511203f65c..12785f280183e03 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2915,6 +2915,11 @@ def fmodule_output : Flag<["-"], "fmodule-output">, Flags<[NoXarchOption]>,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Save intermediate module file results when compiling a standard C++ module unit.">;
 
+def fthinBMI_output_EQ : Joined<["-"], "fthinBMI-output=">, Group<f_Group>,
+  HelpText<"Specify the output path for the thin BMI for C++20 Named modules">,
+  Visibility<[ClangOption, CC1Option, CLOption, DXCOption]>,
+  MarshallingInfoString<FrontendOpts<"ThinBMIPath">>;
+
 def fmodules_prune_interval : Joined<["-"], "fmodules-prune-interval=">, Group<i_Group>,
   Visibility<[ClangOption, CC1Option]>, MetaVarName<"<seconds>">,
   HelpText<"Specify the interval (in seconds) between attempts to prune the module cache">,
@@ -7223,7 +7228,9 @@ def ast_view : Flag<["-"], "ast-view">,
 def emit_module : Flag<["-"], "emit-module">,
   HelpText<"Generate pre-compiled module file from a module map">;
 def emit_module_interface : Flag<["-"], "emit-module-interface">,
-  HelpText<"Generate pre-compiled module file from a C++ module interface">;
+  HelpText<"Generate pre-compiled module file from a standard C++ module interface unit">;
+def emit_thin_module_interface : Flag<["-"], "emit-thin-module-interface">,
+  HelpText<"Generate reduced prebuilt module interface from a standard C++ module interface unit">;
 def emit_header_unit : Flag<["-"], "emit-header-unit">,
   HelpText<"Generate C++20 header units from header files">;
 def emit_pch : Flag<["-"], "emit-pch">,
diff --git a/clang/include/clang/Frontend/FrontendActions.h b/clang/include/clang/Frontend/FrontendActions.h
index 3940e00eeb8dba7..c419deb80034fae 100644
--- a/clang/include/clang/Frontend/FrontendActions.h
+++ b/clang/include/clang/Frontend/FrontendActions.h
@@ -118,6 +118,9 @@ class GenerateModuleAction : public ASTFrontendAction {
   CreateOutputFile(CompilerInstance &CI, StringRef InFile) = 0;
 
 protected:
+  std::vector<std::unique_ptr<ASTConsumer>>
+  CreateMultiplexConsumer(CompilerInstance &CI, StringRef InFile);
+
   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
                                                  StringRef InFile) override;
 
@@ -147,14 +150,27 @@ class GenerateModuleFromModuleMapAction : public GenerateModuleAction {
   CreateOutputFile(CompilerInstance &CI, StringRef InFile) override;
 };
 
+/// Generates fatBMI (which contains full information to generate the object
+/// files) for C++20 Named Modules. Also generates the thin BMI (only contains
+/// necessary information for importers) if `-fthinBMI-output=`.
 class GenerateModuleInterfaceAction : public GenerateModuleAction {
-private:
+protected:
   bool BeginSourceFileAction(CompilerInstance &CI) override;
 
+  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+                                                 StringRef InFile) override;
+
   std::unique_ptr<raw_pwrite_stream>
   CreateOutputFile(CompilerInstance &CI, StringRef InFile) override;
 };
 
+/// Only generates the thin BMI. This action is mainly used by tests.
+class GenerateThinModuleInterfaceAction : public GenerateModuleInterfaceAction {
+private:
+  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+                                                 StringRef InFile) override;
+};
+
 class GenerateHeaderUnitAction : public GenerateModuleAction {
 
 private:
diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h
index 53a8681cfdbba04..719d4ca81336116 100644
--- a/clang/include/clang/Frontend/FrontendOptions.h
+++ b/clang/include/clang/Frontend/FrontendOptions.h
@@ -85,9 +85,13 @@ enum ActionKind {
   /// Generate pre-compiled module from a module map.
   GenerateModule,
 
-  /// Generate pre-compiled module from a C++ module interface file.
+  /// Generate pre-compiled module from a standard C++ module interface unit.
   GenerateModuleInterface,
 
+  /// Generate reduced module interface for a standard C++ module interface
+  /// unit.
+  GenerateThinModuleInterface,
+
   /// Generate a C++20 header unit module from a header file.
   GenerateHeaderUnit,
 
@@ -549,6 +553,9 @@ class FrontendOptions {
   /// Path which stores the output files for -ftime-trace
   std::string TimeTracePath;
 
+  /// Path to the thin BMI for -fthinbmi-output=
+  std::string ThinBMIPath;
+
 public:
   FrontendOptions()
       : DisableFree(false), RelocatablePCH(false), ShowHelp(false),
diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h
index 3019bbc2ddc9cc7..be2d0e227177c34 100644
--- a/clang/include/clang/Serialization/ASTWriter.h
+++ b/clang/include/clang/Serialization/ASTWriter.h
@@ -166,6 +166,10 @@ class ASTWriter : public ASTDeserializationListener,
   /// Indicates that the AST contained compiler errors.
   bool ASTHasCompilerErrors = false;
 
+  /// Indicates that we're going to generate the reduced BMI for C++20
+  /// named modules.
+  bool GeneratingThinBMI = false;
+
   /// Mapping from input file entries to the index into the
   /// offset table where information about that input file is stored.
   llvm::DenseMap<const FileEntry *, uint32_t> InputFileIDs;
@@ -582,7 +586,8 @@ class ASTWriter : public ASTDeserializationListener,
   ASTWriter(llvm::BitstreamWriter &Stream, SmallVectorImpl<char> &Buffer,
             InMemoryModuleCache &ModuleCache,
             ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
-            bool IncludeTimestamps = true, bool BuildingImplicitModule = false);
+            bool IncludeTimestamps = true, bool BuildingImplicitModule = false,
+            bool GeneratingThinBMI = false);
   ~ASTWriter() override;
 
   ASTContext &getASTContext() const {
@@ -813,6 +818,13 @@ class PCHGenerator : public SemaConsumer {
   const ASTWriter &getWriter() const { return Writer; }
   SmallVectorImpl<char> &getPCH() const { return Buffer->Data; }
 
+  bool isComplete() const { return Buffer->IsComplete; }
+  PCHBuffer *getBufferPtr() { return Buffer.get(); }
+  StringRef getOutputFile() const { return OutputFile; }
+  DiagnosticsEngine &getDiagnostics() const {
+    return SemaPtr->getDiagnostics();
+  }
+
 public:
   PCHGenerator(const Preprocessor &PP, InMemoryModuleCache &ModuleCache,
                StringRef OutputFile, StringRef isysroot,
@@ -820,7 +832,8 @@ class PCHGenerator : public SemaConsumer {
                ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
                bool AllowASTWithErrors = false, bool IncludeTimestamps = true,
                bool BuildingImplicitModule = false,
-               bool ShouldCacheASTInMemory = false);
+               bool ShouldCacheASTInMemory = false,
+               bool GeneratingThinBMI = false);
   ~PCHGenerator() override;
 
   void InitializeSema(Sema &S) override { SemaPtr = &S; }
@@ -830,6 +843,20 @@ class PCHGenerator : public SemaConsumer {
   bool hasEmittedPCH() const { return Buffer->IsComplete; }
 };
 
+class ThinBMIGenerator : public PCHGenerator {
+public:
+  ThinBMIGenerator(const Preprocessor &PP, InMemoryModuleCache &ModuleCache,
+                   StringRef OutputFile, std::shared_ptr<PCHBuffer> Buffer,
+                   ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
+                   bool IncludeTimestamps);
+
+  void HandleTranslationUnit(ASTContext &Ctx) override;
+};
+
+/// If the definition may impact the ABI. If yes, we're allowed to eliminate
+/// the definition of D in thin BMI.
+bool MayDefAffectABI(const Decl *D);
+
 /// A simple helper class to pack several bits in order into (a) 32 bit
 /// integer(s).
 class BitsPacker {
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 6f5ff8141032677..76def412d12552c 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -4086,6 +4086,13 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
     }
   }
 
+  // Diagnose misuse of -fthinBMI-output. It should be an error if we specify
+  // -fthinBMI-output with multiple precompilation jobs. Here we didn't check if
+  // there are multiple module units in the inputs.
+  if (C.getArgs().getLastArg(options::OPT_fthinBMI_output_EQ) &&
+      Inputs.size() > 1)
+    Diag(clang::diag::err_drv_thin_bmi_output_argument_with_multiple_files);
+
   handleArguments(C, Args, Inputs, Actions);
 
   bool UseNewOffloadingDriver =
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 22f992166ded6c0..5bb945be78dcb41 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -3940,6 +3940,8 @@ static bool RenderModulesOptions(Compilation &C, const Driver &D,
   Args.ClaimAllArgs(options::OPT_fmodule_output);
   Args.ClaimAllArgs(options::OPT_fmodule_output_EQ);
 
+  Args.AddLastArg(CmdArgs, options::OPT_fthinBMI_output_EQ);
+
   return HaveModules;
 }
 
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 637c6a35af6532b..b6245d0dddb1052 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -2554,6 +2554,7 @@ static const auto &getFrontendActionTable() {
 
       {frontend::GenerateModule, OPT_emit_module},
       {frontend::GenerateModuleInterface, OPT_emit_module_interface},
+      {frontend::GenerateThinModuleInterface, OPT_emit_thin_module_interface},
       {frontend::GenerateHeaderUnit, OPT_emit_header_unit},
       {frontend::GeneratePCH, OPT_emit_pch},
       {frontend::GenerateInterfaceStubs, OPT_emit_interface_stubs},
@@ -4236,6 +4237,7 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
   case frontend::FixIt:
   case frontend::GenerateModule:
   case frontend::GenerateModuleInterface:
+  case frontend::GenerateThinModuleInterface:
   case frontend::GenerateHeaderUnit:
   case frontend::GeneratePCH:
   case frontend::GenerateInterfaceStubs:
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index 2afcf1cf9f68c81..1c66022993ba216 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -184,12 +184,12 @@ bool GeneratePCHAction::BeginSourceFileAction(CompilerInstance &CI) {
   return true;
 }
 
-std::unique_ptr<ASTConsumer>
-GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
-                                        StringRef InFile) {
+std::vector<std::unique_ptr<ASTConsumer>>
+GenerateModuleAction::CreateMultiplexConsumer(CompilerInstance &CI,
+                                              StringRef InFile) {
   std::unique_ptr<raw_pwrite_stream> OS = CreateOutputFile(CI, InFile);
   if (!OS)
-    return nullptr;
+    return {};
 
   std::string OutputFile = CI.getFrontendOpts().OutputFile;
   std::string Sysroot;
@@ -210,6 +210,17 @@ GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
       +CI.getFrontendOpts().BuildingImplicitModule));
   Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator(
       CI, std::string(InFile), OutputFile, std::move(OS), Buffer));
+  return std::move(Consumers);
+}
+
+std::unique_ptr<ASTConsumer>
+GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
+                                        StringRef InFile) {
+  std::vector<std::unique_ptr<ASTConsumer>> Consumers =
+      CreateMultiplexConsumer(CI, InFile);
+  if (Consumers.empty())
+    return nullptr;
+
   return std::make_unique<MultiplexConsumer>(std::move(Consumers));
 }
 
@@ -264,6 +275,38 @@ GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI,
   return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");
 }
 
+static std::unique_ptr<ASTConsumer>
+CreateThinBMIGenerator(CompilerInstance &CI, StringRef OutputFile) {
+  auto Buffer = std::make_shared<PCHBuffer>();
+  // We don't have modules extension in Named mdoules.
+  llvm::SmallVector<std::shared_ptr<ModuleFileExtension>, 1> ModulesExtensions;
+  return std::make_unique<ThinBMIGenerator>(
+      CI.getPreprocessor(), CI.getModuleCache(), OutputFile, Buffer,
+      ModulesExtensions,
+      /*IncludeTimestamps=*/+CI.getFrontendOpts().IncludeTimestamps);
+}
+
+std::unique_ptr<ASTConsumer>
+GenerateModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI,
+                                                 StringRef InFile) {
+  std::vector<std::unique_ptr<ASTConsumer>> Consumers =
+      CreateMultiplexConsumer(CI, InFile);
+  if (Consumers.empty())
+    return nullptr;
+
+  if (!CI.getFrontendOpts().ThinBMIPath.empty())
+    Consumers.push_back(
+        CreateThinBMIGenerator(CI, CI.getFrontendOpts().ThinBMIPath));
+
+  return std::make_unique<MultiplexConsumer>(std::move(Consumers));
+}
+
+std::unique_ptr<ASTConsumer>
+GenerateThinModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI,
+                                                     StringRef InFile) {
+  return CreateThinBMIGenerator(CI, CI.getFrontendOpts().OutputFile);
+}
+
 bool GenerateHeaderUnitAction::BeginSourceFileAction(CompilerInstance &CI) {
   if (!CI.getLangOpts().CPlusPlusModules) {
     CI.getDiagnostics().Report(diag::err_module_interface_requires_cpp_modules);
@@ -830,7 +873,6 @@ void DumpModuleInfoAction::ExecuteAction() {
 
   const LangOptions &LO = getCurrentASTUnit().getLangOpts();
   if (LO.CPlusPlusModules && !LO.CurrentModule.empty()) {
-
     ASTReader *R = getCurrentASTUnit().getASTReader().get();
     unsigned SubModuleCount = R->getTotalNumSubmodules();
     serialization::ModuleFile &MF = R->getModuleManager().getPrimaryModule();
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index b280a1359d2f272..59f7f955db50971 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -65,6 +65,8 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
     return std::make_unique<GenerateModuleFromModuleMapAction>();
   case GenerateModuleInterface:
     return std::make_unique<GenerateModuleInterfaceAction>();
+  case GenerateThinModuleInterface:
+    return std::make_unique<GenerateThinModuleInterfaceAction>();
   case GenerateHeaderUnit:
     return std::make_unique<GenerateHeaderUnitAction>();
   case GeneratePCH:            return std::make_unique<GeneratePCHAction>();
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 0d347d86cb2eb44..ee8ba8a6874b57a 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -4593,10 +4593,12 @@ ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream,
                      SmallVectorImpl<char> &Buffer,
                      InMemoryModuleCache &ModuleCache,
                      ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
-                     bool IncludeTimestamps, bool BuildingImplicitModule)
+                     bool IncludeTimestamps, bool BuildingImplicitModule,
+                     bool GeneratingThinBMI)
     : Stream(Stream), Buffer(Buffer), ModuleCache(ModuleCache),
       IncludeTimestamps(IncludeTimestamps),
-      BuildingImplicitModule(BuildingImplicitModule) {
+      BuildingImplicitModule(BuildingImplicitModule),
+      GeneratingThinBMI(GeneratingThinBMI) {
   for (const auto &Ext : Extensions) {
     if (auto Writer = Ext->createExtensionWriter(*this))
       ModuleFileExtensionWriters.push_back(std::move(Writer));
@@ -5403,18 +5405,20 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
 
     // Add a trailing update record, if any. These must go last because we
     // lazily load their attached statement.
-    if (HasUpdatedBody) {
-      const auto *Def = cast<FunctionDecl>(D);
-      Record.push_back(UPD_CXX_ADDED_FUNCTION_DEFINITION);
-      Record.push_back(Def->isInlined());
-      Record.AddSourceLocation(Def->getInnerLocStart());
-      Record.AddFunctionDefinition(Def);
-    } else if (HasAddedVarDefinition) {
-      const auto *VD = cast<VarDecl>(D);
-      Record.push_back(UPD_CXX_ADDED_VAR_DEFINITION);
-      Record.push_back(VD->isInline());
-      Record.push_back(VD->isInlineSpecified());
-      Record.AddVarDeclInit(VD);
+    if (!GeneratingThinBMI || MayDefAffectABI(D)) {
+      if (HasUpdatedBody) {
+        const auto *Def = cast<FunctionDecl>(D);
+        Record.push_back(UPD_CXX_ADDED_FUNCTION_DEFINITION);
+        Record.push_back(Def->isInlined());
+        Record.AddSourceLocation(Def->getInnerLocStart());
+        Record.AddFunctionDefinition(Def);
+      } else if (HasAddedVarDefinition) {
+        const auto *VD = cast<VarDecl>(D);
+        Record.push_back(UPD_CXX_ADDED_VAR_DEFINITION);
+        Record.push_back(VD->isInline());
+        Record.push_back(VD->isInlineSpecified());
+        Record.AddVarDeclInit(VD);
+      }
     }
 
     OffsetsRecord.push_back(GetDeclRef(D));
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 763b610288f1182..00a04ee2fa730d1 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -16,6 +16,7 @@
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/DeclVisitor.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/ODRHash.h"
 #include "clang/AST/OpenMPClause.h"
 #include "clang/AST/PrettyDeclStackTrace.h"
 #include "clang/Basic/SourceManager.h"
@@ -40,11 +41,14 @@ namespace clang {
     serialization::DeclCode Code;
     unsigned AbbrevToUse;
 
+    bool GeneratingThinBMI = false;
+
   public:
     ASTDeclWriter(ASTWriter &Writer, ASTContext &Context,
-                  ASTWriter::RecordDataImpl &Record)
+                  ASTWriter::RecordDataImpl &Record, bool GeneratingThinBMI)
         : Writer(Writer), Context(Context), Record(Writer, Record),
-          Code((serialization::DeclCode)0), AbbrevToUse(0) {}
+          Code((serialization::DeclCode)0), AbbrevToUse(0),
+          GeneratingThinBMI(GeneratingThinBMI) {}
 
     uint64_t Emit(Decl *D) {
       if (!Code)
@@ -270,6 +274,35 @@ namespace clang {
   };
 }
 
+bool clang::MayDefAffectABI(const Decl *D) {
+  if (auto *FD = dyn_cast<FunctionDecl>(D)) {
+    if (FD->isInlined() || FD->isConstexpr())
+      return true;
+
+    // Non-user-provided functions get emitted as weak definitions with every
+    // use, no matter whether they've been explicitly instantiated etc.
+    if (!FD->isUserProvided())
+      return true;
+    
+    if (FD->isDependentContext())
+      return true;
+
+    if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+      return true;
+  }
+
+  if (auto *VD = dyn_cast<VarDecl>(D)) {
+    if (!VD->getDeclContext()->getRedeclContext()->isFileContext() ||
+        VD->isInline() || VD->isConstexpr() || isa<ParmVarDecl>(VD))
+      return true;
+
+    if (VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+      return true;
+  }
+
+  return false;
+}
+
 void ASTDeclWriter::Visit(Decl *D) {
   DeclVisitor<ASTDeclWriter>::Visit(D);
 
@@ -285,9 +318,12 @@ void ASTDeclWriter::Visit(Decl *D) {
   // have been written. We want it last because we will not read it back when
   // retrieving it from the AST, we'll just lazily set the offset.
   if (auto *FD = dyn_cast<FunctionDecl>(D)) {
-    Record.push_back(FD->doesThisDeclarationHaveABody());
-    if (FD->doesThisDeclarationHaveABody())
-      Record.AddFunctionDefinition(FD);
+    if (!GeneratingThinBMI || MayDefAffectABI(FD)) {
+      Record.push_back(FD->doesThisDeclarationHaveABody());
+      if (FD->doesThisDeclarationHaveABody())
+        Record.AddFunctionDefinition(FD);
+    } else
+      Record.push_back(0);
   }
 
   // Similar to FunctionDecls, handle VarDecl's initializer here and write it
@@ -295,7 +331,10 @@ void ASTDeclWriter::Visit(Decl *D) {
   // we have finished recursive deserialization, because it can recursively
   // refer back to the variable.
   if (auto *VD = dyn_cast<VarDecl>(D)) {
-    Record.AddVarDeclInit(VD);
+    if (!GeneratingThinBMI || MayDefAffectABI(VD))
+      Record.AddVarDeclInit(VD);
+    else
+      Record.push_back(0);
   }
 
   // And similarly for FieldDecls. We already serialized whether there is a
@@ -2486,7 +2525,7 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
   assert(ID >= FirstDeclID && "invalid decl ID");
 
   RecordData Record;
-  ASTDeclWriter W(*this, Context, Record);
+  ASTDeclWriter W(*this, Context, Record, GeneratingThinBMI);
 
   // Build a record for this declaration
   W.Visit(D);
diff --git a/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp
index cf8084333811f13..5d047672d27a1a4 100644
--- a/clang/lib/Serialization/GeneratePCH.cpp
+++ b/clang/lib/Serialization/GeneratePCH.cpp
@@ -12,9 +12,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/ASTContext.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Sema/SemaConsumer.h"
+#include "clang/Serialization/ASTReader.h"
 #include "clang/Serialization/ASTWriter.h"
 #include "llvm/Bitstream/BitstreamWriter.h"
 
@@ -25,11 +27,12 @@ PCHGenerator::PCHGenerator(
     StringRef OutputFile, StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer,
     ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
     bool AllowASTWithErrors, bool IncludeTimestamps,
-    bool BuildingImplicitModule, bool ShouldCacheASTInMemory)
+    bool BuildingImplicitModule, bool ShouldCacheASTInMemory,
+    bool GeneratingThinBMI)
     : PP(PP), OutputFile(OutputFile), isysroot(isysroot.str()),
       SemaPtr(nullptr), Buffer(std::move(Buffer)), Stream(this->Buffer->Data),
       Writer(Stream, this->Buffer->Data, ModuleCache, Extensions,
-             IncludeTimestamps, BuildingImplicitModule),
+             IncludeTimestamps, BuildingImplicitModule, GeneratingThinBMI),
       AllowASTWithErrors(AllowASTWithErrors),
       ShouldCacheASTInMemory(ShouldCacheASTInMemory) {
   this->Buffer->IsComplete = false;
@@ -78,3 +81,32 @@ ASTMutationListener *PCHGenerator::GetASTMutationListener() {
 ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() {
   return &Writer;
 }
+
+ThinBMIGenerator::ThinBMIGenerator(
+    const Preprocessor &PP, InMemoryModuleCache &ModuleCache,
+    StringRef OutputFile, std::shared_ptr<PCHBuffer> Buffer,
+    ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
+    bool IncludeTimestamps)
+    : PCHGenerator(
+          PP, ModuleCache, OutputFile, llvm::StringRef(), Buffer, Extensions,
+          /*AllowASTWithErrors*/ false, /*IncludeTimestamps=*/IncludeTimestamps,
+          /*BuildingImplicitModule=*/false, /*ShouldCacheASTInMemory=*/false,
+          /*GeneratingThinBMI=*/true) {}
+
+void ThinBMIGenerator::HandleTranslationUnit(ASTContext &Ctx) {
+  PCHGenerator::HandleTranslationUnit(Ctx);
+
+  if (!isComplete())
+    return;
+
+  std::error_code EC;
+  auto OS = std::make_unique<llvm::raw_fd_ostream>(getOutputFile(), EC);
+  if (EC) {
+    getDiagnostics().Report(diag::err_fe_unable_to_open_output)
+        << getOutputFile() << EC.message() << "\n";
+    return;
+  }
+
+  *OS << getBufferPtr()->Data;
+  OS->flush();
+}
diff --git a/clang/test/CXX/basic/basic.link/p10-ex2.cpp b/clang/test/CXX/basic/basic.link/p10-ex2.cpp
index 95fdb56f78d6250..98daf12cefc64be 100644
--- a/clang/test/CXX/basic/basic.link/p10-ex2.cpp
+++ b/clang/test/CXX/basic/basic.link/p10-ex2.cpp
@@ -4,8 +4,9 @@
 // RUN: cd %t
 //
 // RUN: %clang_cc1 -std=c++20 M.cpp -fsyntax-only -DTEST_INTERFACE -verify
-// RUN: %clang_cc1 -std=c++20 M.cpp -emit-module-interface -o M.pcm
+// RUN: %clang_cc1 -std=c++20 M.cpp -emit-module-interface -o M.pcm -fthinBMI-output=M.thin.pcm
 // RUN: %clang_cc1 -std=c++20 useM.cpp -fsyntax-only -fmodule-file=M=M.pcm -verify
+// RUN: %clang_cc1 -std=c++20 useM.cpp -fsyntax-only -fmodule-file=M=M.thin.pcm -verify
 
 //--- decls.h
 int f(); // #1, attached to the global module
diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4-friend-in-reachable-class.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4-friend-in-reachable-class.cpp
index 638057cbd681f06..3a46a218bef03bb 100644
--- a/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4-friend-in-reachable-class.cpp
+++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4-friend-in-reachable-class.cpp
@@ -7,8 +7,10 @@
 // RUN: mkdir %t
 // RUN: split-file %s %t
 //
-// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/Friend-in-reachable-class.cppm -o %t/X.pcm
-// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/Friend-in-reachable-class.cppm \
+// RUN:   -fthinBMI-output=%t/X.thin.pcm -o %t/X.pcm
+// RUN: %clang_cc1 -std=c++20 -fmodule-file=X=%t/X.pcm %t/Use.cpp -verify -fsyntax-only
+// RUN: %clang_cc1 -std=c++20 -fmodule-file=X=%t/X.thin.pcm %t/Use.cpp -verify -fsyntax-only
 //
 //--- Friend-in-reachable-class.cppm
 module;
diff --git a/clang/test/Driver/thinBMI-output.cppm b/clang/test/Driver/thinBMI-output.cppm
new file mode 100644
index 000000000000000..e3268dcf6c15987
--- /dev/null
+++ b/clang/test/Driver/thinBMI-output.cppm
@@ -0,0 +1,29 @@
+// It is annoying to handle different slash direction
+// in Windows and Linux. So we disable the test on Windows
+// here.
+// REQUIRES: !system-windows
+// On AIX, the default output for `-c` may be `.s` instead of `.o`,
+// which makes the test fail. So disable the test on AIX.
+// REQUIRES: !system-aix
+//
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang -std=c++20 %t/Hello.cppm -fthinBMI-output=%t/Hello.pcm -c -o %t/Hello.o \
+// RUN:   -### 2>&1 | FileCheck %t/Hello.cppm
+// RUN: %clang -std=c++20 %t/Hello.cppm -fthinBMI-output=%t/Hello.pcm --precompile \
+// RUN:   -o %t/Hello.pcm -### 2>&1 | FileCheck %t/Hello.cppm
+//
+// Tests that we can't use `-fthinBMI-output=` with multiple input files
+// RUN: not %clang -std=c++20 %t/Hello.cppm %t/a.cppm -fthinBMI-output=%t/Hello.pcm  \
+// RUN:     -o %t/a.out -### 2>&1 | FileCheck %t/a.cppm
+
+//--- Hello.cppm
+export module Hello;
+
+// CHECK: "-emit-module-interface"{{.*}}"-fthinBMI-output={{[a-zA-Z0-9./-]*}}Hello.pcm"
+
+//--- a.cppm
+export module a;
+// CHECK: cannot specify -fthinBMI-output when generating multiple module files
diff --git a/clang/test/Modules/InheritDefaultArguments.cppm b/clang/test/Modules/InheritDefaultArguments.cppm
index 0afb46319ff8508..1bf7c3210bf61d7 100644
--- a/clang/test/Modules/InheritDefaultArguments.cppm
+++ b/clang/test/Modules/InheritDefaultArguments.cppm
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use.cppm -verify -fsyntax-only
 
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use.cppm -verify -fsyntax-only
+
 //--- foo.h
 template <typename T, typename U = int>
 class Templ;
diff --git a/clang/test/Modules/Reachability-Private.cpp b/clang/test/Modules/Reachability-Private.cpp
index 9a7c3ba231f179c..e29906ccf743c6b 100644
--- a/clang/test/Modules/Reachability-Private.cpp
+++ b/clang/test/Modules/Reachability-Private.cpp
@@ -9,6 +9,16 @@
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp \
 // RUN: -DTEST_BADINLINE -verify -fsyntax-only
 
+// Test again with thin BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/Private.cppm -emit-thin-module-interface \
+// RUN: -o %t/Private.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp \
+// RUN: -DTEST_BADINLINE -verify -fsyntax-only
+
 //--- Private.cppm
 export module Private;
 #ifdef TEST_BADINLINE
diff --git a/clang/test/Modules/Reachability-func-default-arg.cpp b/clang/test/Modules/Reachability-func-default-arg.cpp
index 0d6d8655d53293e..6bf0bcadc7e76ea 100644
--- a/clang/test/Modules/Reachability-func-default-arg.cpp
+++ b/clang/test/Modules/Reachability-func-default-arg.cpp
@@ -4,6 +4,9 @@
 //
 // RUN: %clang_cc1 -std=c++20 %t/func_default_arg.cppm -emit-module-interface -o %t/func_default_arg.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+
+// RUN: %clang_cc1 -std=c++20 %t/func_default_arg.cppm -emit-thin-module-interface -o %t/func_default_arg.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
 //
 //--- func_default_arg.cppm
 export module func_default_arg;
diff --git a/clang/test/Modules/Reachability-func-ret.cpp b/clang/test/Modules/Reachability-func-ret.cpp
index ca5bbc68d759f93..4bc2e0c5ec29471 100644
--- a/clang/test/Modules/Reachability-func-ret.cpp
+++ b/clang/test/Modules/Reachability-func-ret.cpp
@@ -4,6 +4,9 @@
 //
 // RUN: %clang_cc1 -std=c++20 %t/func_ret.cppm -emit-module-interface -o %t/func_ret.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+
+// RUN: %clang_cc1 -std=c++20 %t/func_ret.cppm -emit-thin-module-interface -o %t/func_ret.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
 //
 //--- func_ret.cppm
 export module func_ret;
diff --git a/clang/test/Modules/Reachability-template-default-arg.cpp b/clang/test/Modules/Reachability-template-default-arg.cpp
index 6fb109e41fcf0a0..3e1bcd1888ef80d 100644
--- a/clang/test/Modules/Reachability-template-default-arg.cpp
+++ b/clang/test/Modules/Reachability-template-default-arg.cpp
@@ -4,6 +4,9 @@
 //
 // RUN: %clang_cc1 -std=c++20 %t/template_default_arg.cppm -emit-module-interface -o %t/template_default_arg.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
+
+// RUN: %clang_cc1 -std=c++20 %t/template_default_arg.cppm -emit-thin-module-interface -o %t/template_default_arg.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
 //
 //--- template_default_arg.cppm
 export module template_default_arg;
diff --git a/clang/test/Modules/Reachability-template-instantiation.cpp b/clang/test/Modules/Reachability-template-instantiation.cpp
index 2170c7b92a370aa..3dd2268a23433aa 100644
--- a/clang/test/Modules/Reachability-template-instantiation.cpp
+++ b/clang/test/Modules/Reachability-template-instantiation.cpp
@@ -5,6 +5,10 @@
 // RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-module-interface -o %t/Templ.pcm
 // RUN: %clang_cc1 -std=c++20 %t/Use.cppm -fprebuilt-module-path=%t -emit-module-interface -o %t/Use.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use.cpp -verify -fsyntax-only
+
+// RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-thin-module-interface -o %t/Templ.pcm
+// RUN: %clang_cc1 -std=c++20 %t/Use.cppm -fprebuilt-module-path=%t -emit-thin-module-interface -o %t/Use.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use.cpp -verify -fsyntax-only
 //
 //--- Templ.h
 #ifndef TEMPL_H
diff --git a/clang/test/Modules/Reachability-using-templates.cpp b/clang/test/Modules/Reachability-using-templates.cpp
index f530e15bd4d2ba4..5dc5b48cbaf8543 100644
--- a/clang/test/Modules/Reachability-using-templates.cpp
+++ b/clang/test/Modules/Reachability-using-templates.cpp
@@ -4,6 +4,9 @@
 //
 // RUN: %clang_cc1 -std=c++20 %t/mod.templates.cppm -emit-module-interface -o %t/mod.templates.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
+
+// RUN: %clang_cc1 -std=c++20 %t/mod.templates.cppm -emit-thin-module-interface -o %t/mod.templates.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
 //
 //--- mod.templates.cppm
 export module mod.templates;
diff --git a/clang/test/Modules/Reachability-using.cpp b/clang/test/Modules/Reachability-using.cpp
index 642b97dd8432c3b..eaa7ed852ed1479 100644
--- a/clang/test/Modules/Reachability-using.cpp
+++ b/clang/test/Modules/Reachability-using.cpp
@@ -4,6 +4,9 @@
 //
 // RUN: %clang_cc1 -std=c++20 %t/mod.cppm -emit-module-interface -o %t/mod.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
+
+// RUN: %clang_cc1 -std=c++20 %t/mod.cppm -emit-thin-module-interface -o %t/mod.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
 //
 //--- mod.cppm
 export module mod;
diff --git a/clang/test/Modules/concept.cppm b/clang/test/Modules/concept.cppm
index 0e85a46411a5448..a41ce72ed9e26b3 100644
--- a/clang/test/Modules/concept.cppm
+++ b/clang/test/Modules/concept.cppm
@@ -5,6 +5,10 @@
 // RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t -DDIFFERENT %t/B.cppm -verify
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/B.cppm -verify
+//
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -o %t/A.full.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t -DDIFFERENT %t/B.cppm -verify
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/B.cppm -verify
 
 //--- foo.h
 #ifndef FOO_H
diff --git a/clang/test/Modules/concept_differ.cppm b/clang/test/Modules/concept_differ.cppm
index ccb29d26e53d134..7341af8f39984bb 100644
--- a/clang/test/Modules/concept_differ.cppm
+++ b/clang/test/Modules/concept_differ.cppm
@@ -5,6 +5,11 @@
 // RUN: %clang_cc1 -x c++ -std=c++20 %t/A.cppm -I%t -emit-module-interface -o %t/A.pcm
 // RUN: %clang_cc1 -x c++ -std=c++20 %t/B.cppm -I%t -emit-module-interface -o %t/B.pcm
 // RUN: %clang_cc1 -x c++ -std=c++20 -fprebuilt-module-path=%t %t/foo.cpp -verify
+//
+// RUN: rm %t/A.pcm %t/B.pcm
+// RUN: %clang_cc1 -x c++ -std=c++20 %t/A.cppm -I%t -emit-thin-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -x c++ -std=c++20 %t/B.cppm -I%t -emit-thin-module-interface -o %t/B.pcm
+// RUN: %clang_cc1 -x c++ -std=c++20 -fprebuilt-module-path=%t %t/foo.cpp -verify
 
 //--- foo.h
 template <class T>
diff --git a/clang/test/Modules/ctor.arg.dep.cppm b/clang/test/Modules/ctor.arg.dep.cppm
index 0e5b1a694f6a5e1..28ab704e5628d7c 100644
--- a/clang/test/Modules/ctor.arg.dep.cppm
+++ b/clang/test/Modules/ctor.arg.dep.cppm
@@ -5,6 +5,10 @@
 // RUN: %clang_cc1 -std=c++20 %t/A.cppm -I%t -emit-module-interface -o %t/A.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
 //
+// RUN: rm %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -I%t -emit-thin-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+//
 //--- foo.h
 
 namespace ns {
diff --git a/clang/test/Modules/cxx20-10-1-ex1.cpp b/clang/test/Modules/cxx20-10-1-ex1.cpp
index b9a5e8023d035f3..772555b25b80a16 100644
--- a/clang/test/Modules/cxx20-10-1-ex1.cpp
+++ b/clang/test/Modules/cxx20-10-1-ex1.cpp
@@ -17,6 +17,19 @@
 // RUN: %clang_cc1 -std=c++20 -emit-obj %t/std10-1-ex1-tu4.cpp \
 // RUN:  -fmodule-file=%t/A.pcm -o %t/ex1.o
 
+// RUN: rm %t/A_Internals.pcm %t/A_Foo.pcm %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-1-ex1-tu1.cpp \
+// RUN:  -o %t/A_Internals.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-1-ex1-tu2.cpp \
+// RUN:  -fmodule-file=%t/A_Internals.pcm -o %t/A_Foo.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-1-ex1-tu3.cpp \
+// RUN:  -fmodule-file=%t/A_Foo.pcm -o %t/A.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-obj %t/std10-1-ex1-tu4.cpp \
+// RUN:  -fmodule-file=%t/A.pcm -o %t/ex1.o
+
 // expected-no-diagnostics
 
 //--- std10-1-ex1-tu1.cpp
diff --git a/clang/test/Modules/cxx20-10-1-ex2.cpp b/clang/test/Modules/cxx20-10-1-ex2.cpp
index 8b908d5fa2eda61..f273655783eec40 100644
--- a/clang/test/Modules/cxx20-10-1-ex2.cpp
+++ b/clang/test/Modules/cxx20-10-1-ex2.cpp
@@ -5,26 +5,50 @@
 
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex2-tu1.cpp \
 // RUN:  -o %t/B_Y.pcm
-
+//
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex2-tu2.cpp \
 // RUN:     -fmodule-file=B:Y=%t/B_Y.pcm -o %t/B.pcm
-
+//
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex2-tu3.cpp \
 // RUN:     -o %t/B_X1.pcm -verify
-
+//
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex2-tu4.cpp \
 // RUN:     -fmodule-file=B=%t/B.pcm -fmodule-file=B:Y=%t/B_Y.pcm  -o %t/B_X2.pcm
-
+//
 // RUN: %clang_cc1 -std=c++20 -emit-obj %t/std10-1-ex2-tu5.cpp \
 // RUN:     -fmodule-file=B=%t/B.pcm -fmodule-file=B:Y=%t/B_Y.pcm  -o %t/b_tu5.o
-
+//
 // RUN: %clang_cc1 -std=c++20 -S %t/std10-1-ex2-tu6.cpp \
 // RUN:     -fmodule-file=B=%t/B.pcm -fmodule-file=B:Y=%t/B_Y.pcm  -o %t/b_tu6.s -verify
-
+//
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex2-tu7.cpp \
 // RUN:     -fmodule-file=B:X2=%t/B_X2.pcm -fmodule-file=B=%t/B.pcm \
 // RUN:     -fmodule-file=B:Y=%t/B_Y.pcm   -o %t/B_X3.pcm -verify
 
+// Test again with thin BMI.
+// RUN: rm %t/B_X2.pcm %t/B.pcm %t/B_Y.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-1-ex2-tu1.cpp \
+// RUN:  -o %t/B_Y.pcm
+//
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-1-ex2-tu2.cpp \
+// RUN:     -fmodule-file=B:Y=%t/B_Y.pcm -o %t/B.pcm
+//
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-1-ex2-tu3.cpp \
+// RUN:     -o %t/B_X1.pcm -verify
+//
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-1-ex2-tu4.cpp \
+// RUN:     -fmodule-file=B=%t/B.pcm -fmodule-file=B:Y=%t/B_Y.pcm  -o %t/B_X2.pcm
+//
+// RUN: %clang_cc1 -std=c++20 -emit-obj %t/std10-1-ex2-tu5.cpp \
+// RUN:     -fmodule-file=B=%t/B.pcm -fmodule-file=B:Y=%t/B_Y.pcm  -o %t/b_tu5.o
+//
+// RUN: %clang_cc1 -std=c++20 -S %t/std10-1-ex2-tu6.cpp \
+// RUN:     -fmodule-file=B=%t/B.pcm -fmodule-file=B:Y=%t/B_Y.pcm  -o %t/b_tu6.s -verify
+//
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-1-ex2-tu7.cpp \
+// RUN:     -fmodule-file=B:X2=%t/B_X2.pcm -fmodule-file=B=%t/B.pcm \
+// RUN:     -fmodule-file=B:Y=%t/B_Y.pcm   -o %t/B_X3.pcm -verify
+
 //--- std10-1-ex2-tu1.cpp
 module B:Y;
 int y();
diff --git a/clang/test/Modules/cxx20-10-2-ex2.cpp b/clang/test/Modules/cxx20-10-2-ex2.cpp
index bc66d6a2ec1a92e..21fae454d5105b7 100644
--- a/clang/test/Modules/cxx20-10-2-ex2.cpp
+++ b/clang/test/Modules/cxx20-10-2-ex2.cpp
@@ -14,6 +14,18 @@
 // RUN: -fmodule-file=%t/std-10-2-ex2-c.pcm -fmodule-file=X=%t/X.pcm \
 // RUN: -pedantic-errors -verify -o  %t/M.pcm
 
+// Test again with thin BMI.
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -I %t \
+// RUN: -xc++-user-header std-10-2-ex2-c.h -o %t/std-10-2-ex2-c.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std-10-2-ex2-tu1.cpp \
+// RUN:  -o  %t/X.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std-10-2-ex2-tu2.cpp \
+// RUN: -fmodule-file=%t/std-10-2-ex2-c.pcm -fmodule-file=X=%t/X.pcm \
+// RUN: -pedantic-errors -verify -o  %t/M.pcm
+
+
 //--- std-10-2-ex2-b.h
 int f();
 
diff --git a/clang/test/Modules/cxx20-10-2-ex5.cpp b/clang/test/Modules/cxx20-10-2-ex5.cpp
index 49c5934c8f2172d..c3555cf8f67eb05 100644
--- a/clang/test/Modules/cxx20-10-2-ex5.cpp
+++ b/clang/test/Modules/cxx20-10-2-ex5.cpp
@@ -13,6 +13,18 @@
 // RUN: %clang_cc1 -std=c++20 -emit-obj %t/std-10-2-ex5-tu3.cpp \
 // RUN:  -fmodule-file=M=%t/M.pcm -verify -o %t/main.o
 
+// Test again with thin BMI.
+// RUN: rm %t/M.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std-10-2-ex5-tu1.cpp \
+// RUN:  -o  %t/M.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-obj %t/std-10-2-ex5-tu2.cpp \
+// RUN:  -fmodule-file=M=%t/M.pcm -o  %t/tu-2.o
+
+// RUN: %clang_cc1 -std=c++20 -emit-obj %t/std-10-2-ex5-tu3.cpp \
+// RUN:  -fmodule-file=M=%t/M.pcm -verify -o %t/main.o
+
+
 //--- std-10-2-ex5-tu1.cpp
 export module M;
 export struct X {
diff --git a/clang/test/Modules/cxx20-10-3-ex1.cpp b/clang/test/Modules/cxx20-10-3-ex1.cpp
index 5d6e2554f753b07..c87e6d084d10c37 100644
--- a/clang/test/Modules/cxx20-10-3-ex1.cpp
+++ b/clang/test/Modules/cxx20-10-3-ex1.cpp
@@ -14,6 +14,20 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-3-ex1-tu4.cpp \
 // RUN:  -fmodule-file=M:Part=%t/M_Part.pcm -o %t/M.pcm
 
+// Test again with thin BMI.
+// RUN: rm %t/M_PartImpl.pcm %t/M.pcm %t/M_Part.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-3-ex1-tu1.cpp \
+// RUN:  -o %t/M_PartImpl.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-3-ex1-tu2.cpp \
+// RUN:  -fmodule-file=M:PartImpl=%t/M_PartImpl.pcm -o %t/M.pcm -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-3-ex1-tu3.cpp \
+// RUN:  -o %t/M_Part.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-3-ex1-tu4.cpp \
+// RUN:  -fmodule-file=M:Part=%t/M_Part.pcm -o %t/M.pcm
+
 //--- std10-3-ex1-tu1.cpp
 module M:PartImpl;
 
diff --git a/clang/test/Modules/cxx20-10-3-ex2.cpp b/clang/test/Modules/cxx20-10-3-ex2.cpp
index b1d6d669c0a0e60..9367114181038e7 100644
--- a/clang/test/Modules/cxx20-10-3-ex2.cpp
+++ b/clang/test/Modules/cxx20-10-3-ex2.cpp
@@ -11,6 +11,16 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-3-ex2-tu3.cpp \
 // RUN:  -o %t/M.pcm -verify
 
+// Test again with thin BMI.
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-3-ex2-tu1.cpp \
+// RUN:  -o %t/M.pcm
+
+// RUN: %clang_cc1 -std=c++20 -S %t/std10-3-ex2-tu2.cpp \
+// RUN:  -fmodule-file=M=%t/M.pcm -o %t/tu_8.s -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/std10-3-ex2-tu3.cpp \
+// RUN:  -o %t/M.pcm -verify
+
 //--- std10-3-ex2-tu1.cpp
 export module M;
 
diff --git a/clang/test/Modules/cxx20-10-5-ex1.cpp b/clang/test/Modules/cxx20-10-5-ex1.cpp
index a83162c5c150171..2eb27d2c93c549a 100644
--- a/clang/test/Modules/cxx20-10-5-ex1.cpp
+++ b/clang/test/Modules/cxx20-10-5-ex1.cpp
@@ -11,6 +11,18 @@
 // RUN: %clang_cc1 -std=c++20 std-10-5-ex1-use.cpp  -fmodule-file=A=A.pcm \
 // RUN:    -fsyntax-only -verify
 
+// Test again with thin BMI.
+// RUN: rm A.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface std-10-5-ex1-interface.cpp \
+// RUN: -DBAD_FWD_DECL  -fsyntax-only -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface std-10-5-ex1-interface.cpp \
+// RUN: -o A.pcm
+
+// RUN: %clang_cc1 -std=c++20 std-10-5-ex1-use.cpp  -fmodule-file=A=A.pcm \
+// RUN:    -fsyntax-only -verify
+
+
 //--- std-10-5-ex1-interface.cpp
 
 export module A;
diff --git a/clang/test/Modules/cxx20-import-diagnostics-a.cpp b/clang/test/Modules/cxx20-import-diagnostics-a.cpp
index a5cf44ed82d5ff3..fb4d5d917a9e3b8 100644
--- a/clang/test/Modules/cxx20-import-diagnostics-a.cpp
+++ b/clang/test/Modules/cxx20-import-diagnostics-a.cpp
@@ -36,6 +36,45 @@
 // RUN: %clang_cc1 -std=c++20 -emit-obj %t/import-diags-tu11.cpp \
 // RUN:  -fmodule-file=C=%t/C.pcm  -o %t/impl.o
 
+// Test again with thin BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/import-diags-tu1.cpp \
+// RUN:  -o %t/B.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/import-diags-tu2.cpp \
+// RUN:  -o %t/C.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/import-diags-tu3.cpp \
+// RUN:  -fmodule-file=B=%t/B.pcm -fmodule-file=C=%t/C.pcm -o %t/AOK1.pcm
+
+// RUN: %clang_cc1 -std=c++20 -S %t/import-diags-tu4.cpp \
+// RUN:  -fmodule-file=AOK1=%t/AOK1.pcm -fmodule-file=B=%t/B.pcm \
+// RUN:  -fmodule-file=C=%t/C.pcm -o %t/tu_3.s -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/import-diags-tu5.cpp \
+// RUN:  -fmodule-file=B=%t/B.pcm -fmodule-file=C=%t/C.pcm -o %t/BC.pcm -verify
+
+// RUN: %clang_cc1 -std=c++20 -S %t/import-diags-tu6.cpp \
+// RUN:  -fmodule-file=B=%t/B.pcm -fmodule-file=C=%t/C.pcm -o %t/tu_5.s -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/import-diags-tu7.cpp \
+// RUN:  -fmodule-file=B=%t/B.pcm -o %t/D.pcm -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/import-diags-tu8.cpp \
+// RUN:  -fmodule-file=B=%t/B.pcm -o %t/D.pcm -verify
+
+// RUN: %clang_cc1 -std=c++20 -S %t/import-diags-tu9.cpp \
+// RUN:  -fmodule-file=B=%t/B.pcm -o %t/tu_8.s -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/import-diags-tu10.cpp \
+// RUN:  -o %t/B.pcm -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-obj %t/import-diags-tu11.cpp \
+// RUN:  -fmodule-file=C=%t/C.pcm  -o %t/impl.o
+
 // Test diagnostics for incorrect module import sequences.
 
 //--- import-diags-tu1.cpp
diff --git a/clang/test/Modules/cxx20-import-diagnostics-b.cpp b/clang/test/Modules/cxx20-import-diagnostics-b.cpp
index 7d432633552a25a..baba79c4384f669 100644
--- a/clang/test/Modules/cxx20-import-diagnostics-b.cpp
+++ b/clang/test/Modules/cxx20-import-diagnostics-b.cpp
@@ -22,6 +22,31 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface  %t/g.cpp \
 // RUN: -fmodule-file=a=%t/a.pcm -o %t/g.pcm -verify
 
+// Test again with thin BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface  %t/a.cpp -o %t/a.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface  %t/c.cpp \
+// RUN: -fmodule-file=a=%t/a.pcm -o %t/c.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface  %t/d.cpp \
+// RUN: -fmodule-file=a=%t/a.pcm -o %t/d.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface  %t/e.cpp \
+// RUN: -fmodule-file=a=%t/a.pcm -o %t/e.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface  %t/a-part.cpp \
+// RUN: -o %t/a-part.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface  %t/f.cpp \
+// RUN: -fmodule-file=a=%t/a.pcm -o %t/f.pcm -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface  %t/g.cpp \
+// RUN: -fmodule-file=a=%t/a.pcm -o %t/g.pcm -verify
+
 //--- a.cpp
 export module a;
 
diff --git a/clang/test/Modules/cxx20-module-file-info-macros.cpp b/clang/test/Modules/cxx20-module-file-info-macros.cpp
index bc7df1c9f50b597..caa7fe49a89db1c 100644
--- a/clang/test/Modules/cxx20-module-file-info-macros.cpp
+++ b/clang/test/Modules/cxx20-module-file-info-macros.cpp
@@ -17,6 +17,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/named_module.cppm -emit-module-interface -o %t/M.pcm
 // RUN: %clang_cc1 -module-file-info %t/M.pcm | FileCheck %t/named_module.cppm
 
+// RUN: %clang_cc1 -std=c++20 %t/named_module.cppm -emit-thin-module-interface -o %t/M.pcm
+// RUN: %clang_cc1 -module-file-info %t/M.pcm | FileCheck %t/named_module.cppm
+
 //--- foo.h
 #pragma once
 #define FOO
diff --git a/clang/test/Modules/deduction-guide.cppm b/clang/test/Modules/deduction-guide.cppm
index 9c959a71365dac9..01ffc990bb06754 100644
--- a/clang/test/Modules/deduction-guide.cppm
+++ b/clang/test/Modules/deduction-guide.cppm
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-module-interface -o %t/Templ.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
 
+// RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-thin-module-interface -o %t/Templ.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+
 //--- foo.h
 template <typename T>
 class Templ {
diff --git a/clang/test/Modules/deduction-guide2.cppm b/clang/test/Modules/deduction-guide2.cppm
index a163c3656831019..c5ae73fe7bbc080 100644
--- a/clang/test/Modules/deduction-guide2.cppm
+++ b/clang/test/Modules/deduction-guide2.cppm
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-module-interface -o %t/Templ.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
 
+// RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-thin-module-interface -o %t/Templ.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+
 //--- Templ.cppm
 export module Templ;
 export template <typename T>
diff --git a/clang/test/Modules/deduction-guide3.cppm b/clang/test/Modules/deduction-guide3.cppm
index 8fa08a0625d7c89..38a817a9e33238b 100644
--- a/clang/test/Modules/deduction-guide3.cppm
+++ b/clang/test/Modules/deduction-guide3.cppm
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-module-interface -o %t/Templ.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
 
+// RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-thin-module-interface -o %t/Templ.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+
 //--- Templ.cppm
 export module Templ;
 template <typename T>
diff --git a/clang/test/Modules/derived_class.cpp b/clang/test/Modules/derived_class.cpp
index ee9e0ae4637ec72..c016d5b0477f4df 100644
--- a/clang/test/Modules/derived_class.cpp
+++ b/clang/test/Modules/derived_class.cpp
@@ -4,6 +4,9 @@
 //
 // RUN: %clang_cc1 -std=c++20 %t/foo.cppm -emit-module-interface -o %t/foo.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
+
+// RUN: %clang_cc1 -std=c++20 %t/foo.cppm -emit-thin-module-interface -o %t/foo.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
 //
 //--- bar.h
 struct bar_base {
diff --git a/clang/test/Modules/duplicated-module-file-eq-module-name.cppm b/clang/test/Modules/duplicated-module-file-eq-module-name.cppm
index e86dbe2b941ef88..1d84a1ce3f6dc0a 100644
--- a/clang/test/Modules/duplicated-module-file-eq-module-name.cppm
+++ b/clang/test/Modules/duplicated-module-file-eq-module-name.cppm
@@ -8,6 +8,10 @@
 // RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm
 // RUN: %clang_cc1 -std=c++20 %t/u.cpp -fmodule-file=a=%t/unexist.pcm \
 // RUN:      -fmodule-file=a=%t/a.pcm -verify -fsyntax-only
+//
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/u.cpp -fmodule-file=a=%t/unexist.pcm \
+// RUN:      -fmodule-file=a=%t/a.pcm -verify -fsyntax-only
 
 //--- a.cppm
 export module a;
diff --git a/clang/test/Modules/enum-class.cppm b/clang/test/Modules/enum-class.cppm
index 01ae8c0d8814da5..0c4f2079a3c5f6b 100644
--- a/clang/test/Modules/enum-class.cppm
+++ b/clang/test/Modules/enum-class.cppm
@@ -6,6 +6,9 @@
 //
 // RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+//
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
 
 //--- foo.h
 enum class foo {
diff --git a/clang/test/Modules/explicitly-specialized-template.cpp b/clang/test/Modules/explicitly-specialized-template.cpp
index 89677254ea739ac..0ccd8aa771f1847 100644
--- a/clang/test/Modules/explicitly-specialized-template.cpp
+++ b/clang/test/Modules/explicitly-specialized-template.cpp
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/X.cppm -emit-module-interface -o %t/X.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
 //
+// RUN: %clang_cc1 -std=c++20 %t/X.cppm -emit-thin-module-interface -o %t/X.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
+//
 //--- foo.h
 #ifndef FOO_H
 #define FOO_H
diff --git a/clang/test/Modules/export-language-linkage.cppm b/clang/test/Modules/export-language-linkage.cppm
index 331a620aaad0613..4927eb18b1523da 100644
--- a/clang/test/Modules/export-language-linkage.cppm
+++ b/clang/test/Modules/export-language-linkage.cppm
@@ -7,6 +7,11 @@
 // RUN: %clang_cc1 -std=c++20 %t/c.cppm -fsyntax-only -verify
 // RUN: %clang_cc1 -module-file-info %t/a.pcm | FileCheck %t/a.cppm
 
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cpp -fmodule-file=a=%t/a.pcm -fsyntax-only -verify
+// RUN: %clang_cc1 -std=c++20 %t/c.cppm -fsyntax-only -verify
+// RUN: %clang_cc1 -module-file-info %t/a.pcm | FileCheck %t/a.cppm
+
 //--- a.cppm
 export module a;
 export extern "C++" int foo() { return 43; }
diff --git a/clang/test/Modules/ftime-trace.cppm b/clang/test/Modules/ftime-trace.cppm
index 48cd4113ec7826c..f8c8f7dfb0b2baf 100644
--- a/clang/test/Modules/ftime-trace.cppm
+++ b/clang/test/Modules/ftime-trace.cppm
@@ -9,5 +9,14 @@
 // RUN: %clang_cc1 -std=c++20 %t/a.pcm -ftime-trace=%t/a.json -o -
 // RUN: ls %t | grep "a.json"
 
+// Test again with thin BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/a.pcm -ftime-trace=%t/a.json -o -
+// RUN: ls %t | grep "a.json"
+
 //--- a.cppm
 export module a;
diff --git a/clang/test/Modules/inconsistent-deduction-guide-linkage.cppm b/clang/test/Modules/inconsistent-deduction-guide-linkage.cppm
index abcbec07f97de06..17740cf1f5fd270 100644
--- a/clang/test/Modules/inconsistent-deduction-guide-linkage.cppm
+++ b/clang/test/Modules/inconsistent-deduction-guide-linkage.cppm
@@ -8,6 +8,12 @@
 // RUN: %clang_cc1 -std=c++20 %t/D.cppm -I%t -emit-module-interface -o %t/D.pcm
 // RUN: %clang_cc1 -std=c++20 -fsyntax-only %t/D-part.cppm -I%t -fprebuilt-module-path=%t -verify
 
+// RUN: %clang_cc1 -std=c++20 %t/B.cppm -I%t -emit-thin-module-interface -o %t/B.pcm
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only %t/A.cppm -I%t -fprebuilt-module-path=%t -verify
+//
+// RUN: %clang_cc1 -std=c++20 %t/D.cppm -I%t -emit-thin-module-interface -o %t/D.pcm
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only %t/D-part.cppm -I%t -fprebuilt-module-path=%t -verify
+
 //--- A.cppm
 module;
 export module baz:A;
diff --git a/clang/test/Modules/inconsistent-export.cppm b/clang/test/Modules/inconsistent-export.cppm
index 5e94d2b37b75785..14689407b45d594 100644
--- a/clang/test/Modules/inconsistent-export.cppm
+++ b/clang/test/Modules/inconsistent-export.cppm
@@ -9,6 +9,19 @@
 // RUN:     -fprebuilt-module-path=%t
 // RUN: %clang_cc1 -std=c++20 %t/use.cppm -fprebuilt-module-path=%t -emit-obj
 
+// Test again with thin BMI.
+// RUN: rm -fr %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/m-a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-thin-module-interface -o %t/m-b.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/m.cppm -emit-thin-module-interface -o %t/m.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/use.cppm -fprebuilt-module-path=%t -emit-obj
+
+
 //--- a.cppm
 export module m:a;
 namespace n {
diff --git a/clang/test/Modules/inherited_arg.cppm b/clang/test/Modules/inherited_arg.cppm
index eb66b70cdce3360..d638882e77980a1 100644
--- a/clang/test/Modules/inherited_arg.cppm
+++ b/clang/test/Modules/inherited_arg.cppm
@@ -7,6 +7,17 @@
 // RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -fprebuilt-module-path=%t -o %t/A.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
 
+// Test again with thin BMI.
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/A-B.cppm -I%t -emit-thin-module-interface -o %t/A-B.pcm
+// RUN: %clang_cc1 -std=c++20 %t/A-C.cppm -I%t -emit-thin-module-interface -o %t/A-C.pcm
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -fprebuilt-module-path=%t -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+
+
 //--- foo.h
 template <typename U, typename T>
 class pair {};
diff --git a/clang/test/Modules/instantiation-argdep-lookup.cppm b/clang/test/Modules/instantiation-argdep-lookup.cppm
index fc9009a5bc13d5a..7d8ff9899cff0b0 100644
--- a/clang/test/Modules/instantiation-argdep-lookup.cppm
+++ b/clang/test/Modules/instantiation-argdep-lookup.cppm
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/A.cppm -I%t -emit-module-interface -o %t/A.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
 //
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -I%t -emit-thin-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+//
 //--- foo.h
 
 namespace ns {
diff --git a/clang/test/Modules/lambdas.cppm b/clang/test/Modules/lambdas.cppm
index 7f00cf6f8682ac4..4d15b1c7c3993a7 100644
--- a/clang/test/Modules/lambdas.cppm
+++ b/clang/test/Modules/lambdas.cppm
@@ -11,6 +11,21 @@
 // RUN:    -o %t/lambdas2.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only \
 // RUN:    -verify -DUSE_LAMBDA2
+//
+// Test again with thin BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/lambdas.cppm -emit-thin-module-interface \
+// RUN:    -o %t/lambdas.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only \
+// RUN:    -verify
+//
+// RUN: %clang_cc1 -std=c++20 %t/lambdas2.cppm -emit-thin-module-interface \
+// RUN:    -o %t/lambdas2.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only \
+// RUN:    -verify -DUSE_LAMBDA2
 
 //--- lambdas.h
 auto l1 = []() constexpr -> int {
diff --git a/clang/test/Modules/merge-concepts-cxx-modules.cpp b/clang/test/Modules/merge-concepts-cxx-modules.cpp
index 3d4f8435531a88c..94a66a4bb0e9dfa 100644
--- a/clang/test/Modules/merge-concepts-cxx-modules.cpp
+++ b/clang/test/Modules/merge-concepts-cxx-modules.cpp
@@ -8,6 +8,18 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/conflicting.cppm -o %t/conflicting.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cppm -fsyntax-only -verify
 
+// Test again with thin BMI.
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/same_as.cppm -o %t/same_as.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface -fprebuilt-module-path=%t %t/concepts.cppm -o %t/concepts.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface -fprebuilt-module-path=%t %t/format.cppm -o %t/format.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/conflicting.cppm -o %t/conflicting.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cppm -fsyntax-only -verify
+
+
 //--- same_as.cppm
 export module same_as;
 export template <class T, class U>
diff --git a/clang/test/Modules/merge-constrained-friends.cpp b/clang/test/Modules/merge-constrained-friends.cpp
index 8f0e9ed83cf2962..ba482355f1c132b 100644
--- a/clang/test/Modules/merge-constrained-friends.cpp
+++ b/clang/test/Modules/merge-constrained-friends.cpp
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++23 %t/A.cppm -emit-module-interface -o %t/A.pcm
 // RUN: %clang_cc1 -std=c++23 %t/Use.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++23 %t/A.cppm -emit-thin-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++23 %t/Use.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+
 //--- A.cppm
 module;
 export module A;
diff --git a/clang/test/Modules/merge-lambdas.cppm b/clang/test/Modules/merge-lambdas.cppm
index a1d04ab4e234dd3..2225d50f4005f2d 100644
--- a/clang/test/Modules/merge-lambdas.cppm
+++ b/clang/test/Modules/merge-lambdas.cppm
@@ -6,6 +6,10 @@
 // RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-module-interface -o %t/B.pcm
 // RUN: %clang_cc1 -std=c++20 %t/use.cppm -fprebuilt-module-path=%t -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-thin-module-interface -o %t/B.pcm
+// RUN: %clang_cc1 -std=c++20 %t/use.cppm -fprebuilt-module-path=%t -fsyntax-only -verify
+
 //--- lambda.h
 inline auto cmp = [](auto l, auto r) {
   return l < r;
diff --git a/clang/test/Modules/merge-requires-with-lambdas.cppm b/clang/test/Modules/merge-requires-with-lambdas.cppm
index 5767492047684b9..038b8e2f42d5d54 100644
--- a/clang/test/Modules/merge-requires-with-lambdas.cppm
+++ b/clang/test/Modules/merge-requires-with-lambdas.cppm
@@ -17,6 +17,25 @@
 // RUN: %clang_cc1 -std=c++20 %t/A3.cppm -emit-module-interface -o %t/A3.pcm
 // RUN: %clang_cc1 -std=c++20 %t/TestA3.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
 
+// Test again with thin BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 %t/A0.cppm -emit-thin-module-interface -o %t/A0.pcm
+// RUN: %clang_cc1 -std=c++20 %t/TestA.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+//
+// RUN: %clang_cc1 -std=c++20 %t/A1.cppm -emit-thin-module-interface -o %t/A1.pcm
+// RUN: %clang_cc1 -std=c++20 %t/TestA1.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+//
+// RUN: %clang_cc1 -std=c++20 %t/A2.cppm -emit-thin-module-interface -o %t/A2.pcm
+// RUN: %clang_cc1 -std=c++20 %t/TestA2.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+//
+// RUN: %clang_cc1 -std=c++20 %t/A3.cppm -emit-thin-module-interface -o %t/A3.pcm
+// RUN: %clang_cc1 -std=c++20 %t/TestA3.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+
+
 //--- A.h
 template <class _Tp>
 concept A = requires(const _Tp& __t) { []<class __Up>(const __Up&) {}(__t); };
diff --git a/clang/test/Modules/merge-var-template-spec-cxx-modules.cppm b/clang/test/Modules/merge-var-template-spec-cxx-modules.cppm
index a451bfe7804d332..8fd225c894ac9f5 100644
--- a/clang/test/Modules/merge-var-template-spec-cxx-modules.cppm
+++ b/clang/test/Modules/merge-var-template-spec-cxx-modules.cppm
@@ -7,6 +7,11 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface -fprebuilt-module-path=%t %t/reexport2.cppm -o %t/reexport2.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/use.cppm -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/var_def.cppm -o %t/var_def.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface -fprebuilt-module-path=%t %t/reexport1.cppm -o %t/reexport1.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface -fprebuilt-module-path=%t %t/reexport2.cppm -o %t/reexport2.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/use.cppm -fsyntax-only -verify
+
 //--- use.cppm
 import reexport1;
 import reexport2;
diff --git a/clang/test/Modules/mismatch-diagnostics.cpp b/clang/test/Modules/mismatch-diagnostics.cpp
index f8ce987cfba5727..741ecf15680b05a 100644
--- a/clang/test/Modules/mismatch-diagnostics.cpp
+++ b/clang/test/Modules/mismatch-diagnostics.cpp
@@ -13,6 +13,17 @@
 // RUN:     -fprebuilt-module-path=%t/prebuilt_modules -DCHECK_MISMATCH \
 // RUN:     %t/use.cpp 2>&1 | FileCheck %s
 
+// Test again with thin BMI.
+// RUN: %clang_cc1 -triple %itanium_abi_triple                          \
+// RUN:     -std=c++20 -fprebuilt-module-path=%t/prebuilt-modules       \
+// RUN:     -emit-thin-module-interface -pthread -DBUILD_MODULE              \
+// RUN:     %t/mismatching_module.cppm -o                               \
+// RUN:     %t/prebuilt_modules/mismatching_module.pcm
+//
+// RUN: not %clang_cc1 -triple %itanium_abi_triple -std=c++20           \
+// RUN:     -fprebuilt-module-path=%t/prebuilt_modules -DCHECK_MISMATCH \
+// RUN:     %t/use.cpp 2>&1 | FileCheck %s
+
 //--- mismatching_module.cppm
 export module mismatching_module;
 
diff --git a/clang/test/Modules/module-init-duplicated-import.cppm b/clang/test/Modules/module-init-duplicated-import.cppm
index de0ce1962f10082..5a5632699ed2609 100644
--- a/clang/test/Modules/module-init-duplicated-import.cppm
+++ b/clang/test/Modules/module-init-duplicated-import.cppm
@@ -9,6 +9,17 @@
 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.pcm  \
 // RUN:     -S -emit-llvm -o - | FileCheck %t/m.cppm
 
+// Test again with thin BMI.
+// Note that we can't use thin BMI here for m.cppm since it is required
+// to generate the backend code.
+// RUN: rm %t/a.pcm %t/m.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/a.cppm \
+// RUN:      -emit-thin-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.cppm \
+// RUN:      -emit-module-interface -fmodule-file=a=%t/a.pcm -o %t/m.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.pcm  \
+// RUN:     -S -emit-llvm -o - | FileCheck %t/m.cppm
+
 //--- a.cppm
 export module a;
 export struct A {
diff --git a/clang/test/Modules/named-modules-adl-2.cppm b/clang/test/Modules/named-modules-adl-2.cppm
index 655acfcd93f69ab..e1e009199d398a2 100644
--- a/clang/test/Modules/named-modules-adl-2.cppm
+++ b/clang/test/Modules/named-modules-adl-2.cppm
@@ -6,6 +6,10 @@
 // RUN: %clang_cc1 -std=c++20 %t/b.cppm -fmodule-file=a=%t/a.pcm -emit-module-interface -o %t/b.pcm
 // RUN: %clang_cc1 -std=c++20 %t/c.cppm -fmodule-file=a=%t/a.pcm -fmodule-file=b=%t/b.pcm -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fmodule-file=a=%t/a.pcm -emit-thin-module-interface -o %t/b.pcm
+// RUN: %clang_cc1 -std=c++20 %t/c.cppm -fmodule-file=a=%t/a.pcm -fmodule-file=b=%t/b.pcm -fsyntax-only -verify
+
 //--- a.cppm
 export module a;
 
diff --git a/clang/test/Modules/named-modules-adl-3.cppm b/clang/test/Modules/named-modules-adl-3.cppm
index 2fc2962c926b1b6..37119e3cc742f4a 100644
--- a/clang/test/Modules/named-modules-adl-3.cppm
+++ b/clang/test/Modules/named-modules-adl-3.cppm
@@ -14,6 +14,23 @@
 // RUN: %clang_cc1 -std=c++20 -DEXPORT_OPERATOR %t/c.cppm -fmodule-file=a=%t/a.pcm \
 // RUN:     -fmodule-file=b=%t/b.pcm -fsyntax-only -verify
 
+// Test again with thin BMI.
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fmodule-file=a=%t/a.pcm  -emit-thin-module-interface \
+// RUN:     -o %t/b.pcm
+// RUN: %clang_cc1 -std=c++20 %t/c.cppm -fmodule-file=a=%t/a.pcm -fmodule-file=b=%t/b.pcm \
+// RUN:     -fsyntax-only -verify
+//
+// RUN: %clang_cc1 -std=c++20 -DEXPORT_OPERATOR %t/a.cppm -emit-thin-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 -DEXPORT_OPERATOR %t/b.cppm -fmodule-file=a=%t/a.pcm  \
+// RUN:     -emit-thin-module-interface -o %t/b.pcm
+// RUN: %clang_cc1 -std=c++20 -DEXPORT_OPERATOR %t/c.cppm -fmodule-file=a=%t/a.pcm \
+// RUN:     -fmodule-file=b=%t/b.pcm -fsyntax-only -verify
+
 //--- foo.h
 namespace n {
 
diff --git a/clang/test/Modules/named-modules-adl.cppm b/clang/test/Modules/named-modules-adl.cppm
index d5133ef367265a8..655a57374bef54b 100644
--- a/clang/test/Modules/named-modules-adl.cppm
+++ b/clang/test/Modules/named-modules-adl.cppm
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm
 // RUN: %clang_cc1 -std=c++20 %t/b.cppm -fmodule-file=a=%t/a.pcm -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fmodule-file=a=%t/a.pcm -fsyntax-only -verify
+
 //--- a.h
 namespace n {
 
diff --git a/clang/test/Modules/no-duplicate-codegen-in-GMF.cppm b/clang/test/Modules/no-duplicate-codegen-in-GMF.cppm
index e4d06415fabd453..b088288591bbef4 100644
--- a/clang/test/Modules/no-duplicate-codegen-in-GMF.cppm
+++ b/clang/test/Modules/no-duplicate-codegen-in-GMF.cppm
@@ -9,6 +9,14 @@
 // RUN:     -fprebuilt-module-path=%t
 // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/B.pcm -S -emit-llvm -o - | FileCheck %t/B.cppm
 
+// Test again with thin BMI. Note that we need to generate fat BMI for B.cppm
+// since it is required to generate backend codes.
+// RUN: rm %t/A.pcm %t/B.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/A.cppm -emit-thin-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/B.cppm -emit-module-interface -o %t/B.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/B.pcm -S -emit-llvm -o - | FileCheck %t/B.cppm
+
 //--- foo.h
 
 template <class T>
diff --git a/clang/test/Modules/pair-unambiguous-ctor.cppm b/clang/test/Modules/pair-unambiguous-ctor.cppm
index eb242244260cbdf..3d5269904042df2 100644
--- a/clang/test/Modules/pair-unambiguous-ctor.cppm
+++ b/clang/test/Modules/pair-unambiguous-ctor.cppm
@@ -10,6 +10,15 @@
 // RUN: %clang_cc1 -std=c++20 %t/algorithm.cppm -I%t -emit-module-interface -o %t/std-algorithm.pcm
 // RUN: %clang_cc1 -std=c++20 %t/Use.cppm -I%t -fprebuilt-module-path=%t -emit-module-interface -verify -o %t/Use.pcm
 
+// Test again with thin BMI.
+// RUN: rm -fr %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/string.cppm -I%t -emit-thin-module-interface -o %t/std-string.pcm
+// RUN: %clang_cc1 -std=c++20 %t/algorithm.cppm -I%t -emit-thin-module-interface -o %t/std-algorithm.pcm
+// RUN: %clang_cc1 -std=c++20 %t/Use.cppm -I%t -fprebuilt-module-path=%t -emit-thin-module-interface -verify -o %t/Use.pcm
+
 //--- Use.cppm
 // expected-no-diagnostics
 module;
diff --git a/clang/test/Modules/partial_specialization.cppm b/clang/test/Modules/partial_specialization.cppm
index 3a01857172112e1..10e766a6bb834a9 100644
--- a/clang/test/Modules/partial_specialization.cppm
+++ b/clang/test/Modules/partial_specialization.cppm
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/A.cppm -o %t/A.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
 //
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/A.cppm -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
+//
 //--- foo.h
 template<typename T, typename U>
 inline constexpr bool IsSame = false;
diff --git a/clang/test/Modules/placement-new-reachable.cpp b/clang/test/Modules/placement-new-reachable.cpp
index 29263173d78f458..c6f6e264acf45a4 100644
--- a/clang/test/Modules/placement-new-reachable.cpp
+++ b/clang/test/Modules/placement-new-reachable.cpp
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm
 // RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+
 //--- placement.h
 namespace std {
   using size_t = decltype(sizeof(0));
diff --git a/clang/test/Modules/polluted-operator.cppm b/clang/test/Modules/polluted-operator.cppm
index b24464aa6ad21ef..fa92a8fb1a684e7 100644
--- a/clang/test/Modules/polluted-operator.cppm
+++ b/clang/test/Modules/polluted-operator.cppm
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/a.cppm -o %t/a.pcm
 // RUN: %clang_cc1 -std=c++20 %t/b.cppm -fprebuilt-module-path=%t -emit-module-interface -o %t/b.pcm -verify
 
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/a.cppm -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fprebuilt-module-path=%t -emit-thin-module-interface -o %t/b.pcm -verify
+
 //--- foo.h
 
 namespace std
diff --git a/clang/test/Modules/pr54457.cppm b/clang/test/Modules/pr54457.cppm
index ed67ec1065376ef..8a195dbe4958677 100644
--- a/clang/test/Modules/pr54457.cppm
+++ b/clang/test/Modules/pr54457.cppm
@@ -9,6 +9,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/C.cppm -emit-module-interface -o %t/C.pcm
 // RUN: %clang_cc1 -std=c++20 %t/UseC.cppm -fprebuilt-module-path=%t -verify -S -o -
 
+// RUN: %clang_cc1 -std=c++20 %t/C.cppm -emit-thin-module-interface -o %t/C.pcm
+// RUN: %clang_cc1 -std=c++20 %t/UseC.cppm -fprebuilt-module-path=%t -verify -S -o -
+
 //--- A.cppm
 // expected-no-diagnostics
 export module A;
diff --git a/clang/test/Modules/pr56916.cppm b/clang/test/Modules/pr56916.cppm
index a435b06d5cf1523..98299af7c894129 100644
--- a/clang/test/Modules/pr56916.cppm
+++ b/clang/test/Modules/pr56916.cppm
@@ -8,6 +8,18 @@
 // RUN:     -fprebuilt-module-path=%t
 // RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fsyntax-only -fprebuilt-module-path=%t -verify
 
+// Test again with thin BMI.
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -o %t/M-A.pcm
+// RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-thin-module-interface -o %t/M-B.pcm
+// RUN: %clang_cc1 -std=c++20 %t/M.cppm -emit-thin-module-interface -o %t/M.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fsyntax-only -fprebuilt-module-path=%t -verify
+
+
 //--- foo.h
 template <typename T>
 class Templ {
diff --git a/clang/test/Modules/pr58532.cppm b/clang/test/Modules/pr58532.cppm
index cf530b4ac2ccce5..cc584914ef3ca46 100644
--- a/clang/test/Modules/pr58532.cppm
+++ b/clang/test/Modules/pr58532.cppm
@@ -7,6 +7,12 @@
 // RUN: %clang_cc1 -std=c++20 %t/implementation.cpp -fmodule-file=m=%t/m.pcm \
 // RUN:     -fsyntax-only -verify
 
+// Test again with thin BMI.
+// RUN: %clang_cc1 -std=c++20 %t/interface.cppm -emit-thin-module-interface \
+// RUN:     -o %t/m.pcm
+// RUN: %clang_cc1 -std=c++20 %t/implementation.cpp -fmodule-file=m=%t/m.pcm \
+// RUN:     -fsyntax-only -verify
+
 //--- invisible.h
 #pragma once // This breaks things.
 const int kInvisibleSymbol = 0;
diff --git a/clang/test/Modules/pr58716.cppm b/clang/test/Modules/pr58716.cppm
index 3f97fca7d5e8a32..177802fe3afcb89 100644
--- a/clang/test/Modules/pr58716.cppm
+++ b/clang/test/Modules/pr58716.cppm
@@ -8,7 +8,7 @@
 //
 // RUN: %clang_cc1 -triple=x86_64-linux-gnu -std=c++20 -emit-module-interface %t/m.cppm -o %t/m.pcm
 // RUN: %clang_cc1 -triple=x86_64-linux-gnu -std=c++20 %t/m.pcm -S -emit-llvm -o - | FileCheck %t/m.cppm
-//
+
 //--- m.cppm
 module;
 #include "fail.h"
diff --git a/clang/test/Modules/pr59719.cppm b/clang/test/Modules/pr59719.cppm
index 5aea8992a0ca85b..f1ef69dc04d248f 100644
--- a/clang/test/Modules/pr59719.cppm
+++ b/clang/test/Modules/pr59719.cppm
@@ -7,6 +7,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/data.cppm -emit-module-interface -o %t/data.pcm
 // RUN: %clang_cc1 -std=c++20 %t/main.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++20 %t/data.cppm -emit-thin-module-interface -o %t/data.pcm
+// RUN: %clang_cc1 -std=c++20 %t/main.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+
 //--- foo.h
 namespace std {
 
diff --git a/clang/test/Modules/pr59780.cppm b/clang/test/Modules/pr59780.cppm
index d4bbd52c13f1a4a..211ed67fccf6aa7 100644
--- a/clang/test/Modules/pr59780.cppm
+++ b/clang/test/Modules/pr59780.cppm
@@ -9,6 +9,14 @@
 // RUN:     -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %t/use.cpp
 // RUN: %clang_cc1 -std=c++20 %t/a.pcm -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %t/a.cppm
 
+// Test again with thin BMI.
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -triple %itanium_abi_triple -emit-module-interface \
+// RUN:     -fthinBMI-output=%t/a.pcm -o %t/a.full.pcm
+// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fprebuilt-module-path=%t -S \
+// RUN:     -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %t/use.cpp
+// RUN: %clang_cc1 -std=c++20 %t/a.full.pcm -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %t/a.cppm
+
+
 //--- a.cppm
 export module a;
 
diff --git a/clang/test/Modules/pr59999.cppm b/clang/test/Modules/pr59999.cppm
index 23710de9fe1c559..da59da4b7c1405e 100644
--- a/clang/test/Modules/pr59999.cppm
+++ b/clang/test/Modules/pr59999.cppm
@@ -11,6 +11,19 @@
 // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/Object.pcm \
 // RUN:     -fmodule-file=Module=%t/Module.pcm -S -emit-llvm -o - | FileCheck %t/Object.cppm
 
+// Test again with thin BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/Module.cppm \
+// RUN:     -emit-thin-module-interface -o %t/Module.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/Object.cppm \
+// RUN:     -fmodule-file=Module=%t/Module.pcm -emit-module-interface -o %t/Object.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/Object.pcm \
+// RUN:     -fmodule-file=Module=%t/Module.pcm -S -emit-llvm -o - | FileCheck %t/Object.cppm
+
+
 //--- Module.cppm
 export module Module;
 
diff --git a/clang/test/Modules/pr60036.cppm b/clang/test/Modules/pr60036.cppm
index 297132cfde60bdb..02f6e4fb01cfd79 100644
--- a/clang/test/Modules/pr60036.cppm
+++ b/clang/test/Modules/pr60036.cppm
@@ -24,6 +24,20 @@
 // RUN:		-fmodule-file=c=%t/c.pcm -fmodule-file=d=%t/d.pcm -fmodule-file=e=%t/e.pcm \
 // RUN:		-fmodule-file=f=%t/f.pcm -verify -fsyntax-only 
 
+// Test again with thin BMI
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-thin-module-interface -fprebuilt-module-path=%t -o %t/b.pcm
+// RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-thin-module-interface -fprebuilt-module-path=%t -o %t/c.pcm
+// RUN: %clang_cc1 -std=c++20 %t/d.cppm -emit-thin-module-interface -fprebuilt-module-path=%t -o %t/d.pcm
+// RUN: %clang_cc1 -std=c++20 %t/e.cppm -emit-thin-module-interface -fprebuilt-module-path=%t -o %t/e.pcm
+// RUN: %clang_cc1 -std=c++20 %t/f.cppm -emit-thin-module-interface -fprebuilt-module-path=%t -o %t/f.pcm
+// RUN: %clang_cc1 -std=c++20 %t/g.cppm -fprebuilt-module-path=%t -verify -fsyntax-only 
+
+
 //--- a.cppm
 export module a;
 
diff --git a/clang/test/Modules/pr60085.cppm b/clang/test/Modules/pr60085.cppm
index fba601206404717..abe7bab3073edee 100644
--- a/clang/test/Modules/pr60085.cppm
+++ b/clang/test/Modules/pr60085.cppm
@@ -27,6 +27,23 @@
 // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.pcm \
 // RUN:     -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/a.cppm
 
+// Test again with thin BMI.
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/d.cppm \
+// RUN:     -emit-thin-module-interface -o %t/d.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/c.cppm \
+// RUN:     -emit-thin-module-interface -o %t/c.pcm -fmodule-file=%t/d.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.cppm \
+// RUN:     -emit-thin-module-interface -o %t/b.pcm -fmodule-file=%t/d.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.cppm \
+// RUN:     -emit-module-interface -o %t/a.pcm -fmodule-file=%t/d.pcm \
+// RUN:     -fmodule-file=%t/c.pcm -fmodule-file=%t/b.pcm 
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.pcm \
+// RUN:     -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/a.cppm
+
 //--- d.cppm
 export module d;
 
diff --git a/clang/test/Modules/pr60275.cppm b/clang/test/Modules/pr60275.cppm
index 57b31c6952bea94..48a199782ec93a2 100644
--- a/clang/test/Modules/pr60275.cppm
+++ b/clang/test/Modules/pr60275.cppm
@@ -5,7 +5,12 @@
 // RUN: split-file %s %t
 //
 // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -emit-module-interface %t/a.cppm -o %t/a.pcm
-// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.cpp -fmodule-file=%t/a.pcm -emit-llvm -o - | FileCheck %t/b.cpp
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.cpp -fmodule-file=a=%t/a.pcm -emit-llvm -o - | FileCheck %t/b.cpp
+
+// Test again with thin BMI
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -emit-thin-module-interface %t/a.cppm -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.cpp -fmodule-file=a=%t/a.pcm -emit-llvm -o - | FileCheck %t/b.cpp
+
 //--- foo.h
 
 consteval void global() {}
diff --git a/clang/test/Modules/pr60486.cppm b/clang/test/Modules/pr60486.cppm
index 13802a4917e6e7f..13d37771f2ce8ad 100644
--- a/clang/test/Modules/pr60486.cppm
+++ b/clang/test/Modules/pr60486.cppm
@@ -7,6 +7,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm
 // RUN: %clang_cc1 -std=c++20 -fmodule-file=a=%t/a.pcm %t/b.cppm -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 -fmodule-file=a=%t/a.pcm %t/b.cppm -fsyntax-only -verify
+
 //--- foo.h
 template<typename = void>
 struct s {
diff --git a/clang/test/Modules/pr60693.cppm b/clang/test/Modules/pr60693.cppm
index c50791083a5beae..08e3e4ab39ec3e4 100644
--- a/clang/test/Modules/pr60693.cppm
+++ b/clang/test/Modules/pr60693.cppm
@@ -7,6 +7,10 @@
 // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.cppm -emit-module-interface -o %t/a.pcm
 // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -fmodule-file=a=%t/a.pcm %t/c.cpp -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/c.cpp
 
+// Test again with thin BMI
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.cppm -emit-thin-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -fmodule-file=a=%t/a.pcm %t/c.cpp -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/c.cpp
+
 //--- a.cppm
 export module a;
 
diff --git a/clang/test/Modules/pr60775.cppm b/clang/test/Modules/pr60775.cppm
index 4db027ba3600a98..2830b80a2101158 100644
--- a/clang/test/Modules/pr60775.cppm
+++ b/clang/test/Modules/pr60775.cppm
@@ -12,6 +12,19 @@
 // RUN: %clang_cc1 -std=c++20 %t/f.cppm -emit-module-interface -fmodule-file=c=%t/c.pcm -o %t/f.pcm
 // RUN: %clang_cc1 -std=c++20 %t/g.cpp -fmodule-file=f=%t/f.pcm -fmodule-file=c=%t/c.pcm  -verify -fsyntax-only
 
+// Test again with thin BMI
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -I%t -emit-thin-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cpp -fmodule-file=a=%t/a.pcm -verify -fsyntax-only
+// RUN: %clang_cc1 -std=c++20 %t/c.cppm -I%t -emit-thin-module-interface -o %t/c.pcm
+// RUN: %clang_cc1 -std=c++20 %t/d.cppm -emit-thin-module-interface -fmodule-file=c=%t/c.pcm -o %t/d.pcm
+// RUN: %clang_cc1 -std=c++20 %t/e.cpp -fmodule-file=d=%t/d.pcm -fmodule-file=c=%t/c.pcm -verify -fsyntax-only
+// RUN: %clang_cc1 -std=c++20 %t/f.cppm -emit-thin-module-interface -fmodule-file=c=%t/c.pcm -o %t/f.pcm
+// RUN: %clang_cc1 -std=c++20 %t/g.cpp -fmodule-file=f=%t/f.pcm -fmodule-file=c=%t/c.pcm  -verify -fsyntax-only
+
 //--- initializer_list.h
 namespace std {
   typedef decltype(sizeof(int)) size_t;
diff --git a/clang/test/Modules/pr60890.cppm b/clang/test/Modules/pr60890.cppm
index 2560bec5b43351a..9d3381e4de00015 100644
--- a/clang/test/Modules/pr60890.cppm
+++ b/clang/test/Modules/pr60890.cppm
@@ -9,6 +9,12 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/c.cppm -fprebuilt-module-path=%t -o %t/c.pcm
 // RUN: %clang_cc1 -std=c++20 %t/d.cpp -fprebuilt-module-path=%t -S -emit-llvm -o -
 
+// Test again with thin BMI
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/a.cppm -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/b.cppm -fprebuilt-module-path=%t -o %t/b.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/c.cppm -fprebuilt-module-path=%t -o %t/c.pcm
+// RUN: %clang_cc1 -std=c++20 %t/d.cpp -fprebuilt-module-path=%t -S -emit-llvm -o -
+
 //--- a.cppm
 export module a;
  
diff --git a/clang/test/Modules/pr61065.cppm b/clang/test/Modules/pr61065.cppm
index cf6fcdda78cd446..3437aaa33f4a6ad 100644
--- a/clang/test/Modules/pr61065.cppm
+++ b/clang/test/Modules/pr61065.cppm
@@ -10,6 +10,19 @@
 // DISABLED:     -fprebuilt-module-path=%t
 // DISABLED: %clang_cc1 -std=c++20 %t/d.cpp -fsyntax-only -verify -fprebuilt-module-path=%t
 
+// Test again with thin BMI
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-thin-module-interface -o %t/b.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// DISABLED: %clang_cc1 -std=c++20 %t/c.cppm -emit-thin-module-interface -o %t/c.pcm \
+// DISABLED:     -fprebuilt-module-path=%t
+// DISABLED: %clang_cc1 -std=c++20 %t/d.cpp -fsyntax-only -verify -fprebuilt-module-path=%t
+
+
 //--- a.cppm
 export module a;
 
diff --git a/clang/test/Modules/pr61065_2.cppm b/clang/test/Modules/pr61065_2.cppm
index 10cc1a06b7e450a..9a815f8edf3e057 100644
--- a/clang/test/Modules/pr61065_2.cppm
+++ b/clang/test/Modules/pr61065_2.cppm
@@ -11,6 +11,21 @@
 // RUN:     -fprebuilt-module-path=%t
 // RUN: %clang_cc1 -std=c++20 %t/e.cpp -fsyntax-only -verify -fprebuilt-module-path=%t
 
+// Test again with thin BMI
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-thin-module-interface -o %t/b.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-thin-module-interface -o %t/c.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/d.cppm -emit-thin-module-interface -o %t/d.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/e.cpp -fsyntax-only -verify -fprebuilt-module-path=%t
+
+
 //--- a.cppm
 export module a;
 
diff --git a/clang/test/Modules/pr61067.cppm b/clang/test/Modules/pr61067.cppm
index 8469a1db1f1c8d0..9842b0a4f15f323 100644
--- a/clang/test/Modules/pr61067.cppm
+++ b/clang/test/Modules/pr61067.cppm
@@ -12,6 +12,20 @@
 // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/c.cpp -fmodule-file=a=%t/a.pcm \
 // RUN:     -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/c.cpp
 
+// Test again with thin BMI
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.cppm \
+// RUN:     -emit-thin-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.cppm \
+// RUN:     -emit-module-interface -fmodule-file=a=%t/a.pcm -o %t/b.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.pcm -S \
+// RUN:     -emit-llvm -disable-llvm-passes -o - | FileCheck %t/b.cppm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/c.cpp -fmodule-file=a=%t/a.pcm \
+// RUN:     -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/c.cpp
+
 //--- a.cppm
 export module a;
 
diff --git a/clang/test/Modules/pr61317.cppm b/clang/test/Modules/pr61317.cppm
index 4b54d26dc5a63bb..7b7ec80a6b953fa 100644
--- a/clang/test/Modules/pr61317.cppm
+++ b/clang/test/Modules/pr61317.cppm
@@ -8,6 +8,15 @@
 // RUN:     -fprebuilt-module-path=%t
 // RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
 
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-thin-module-interface -o %t/B.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+
 //--- foo.h
 #ifndef _FOO
 #define _FOO
diff --git a/clang/test/Modules/pr61783.cppm b/clang/test/Modules/pr61783.cppm
index 9cf773b0b282baa..4555787f591735a 100644
--- a/clang/test/Modules/pr61783.cppm
+++ b/clang/test/Modules/pr61783.cppm
@@ -9,6 +9,14 @@
 // RUN: %clang_cc1 -std=c++20 -triple x86_64-pc-windows-msvc19.11.0 -fms-extensions %t/user.cpp -fmodule-file=mod=%t/mod.pcm \
 // RUN:     -S -emit-llvm -o - | FileCheck %t/user.cpp
 
+// Test again with thin BMI
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-pc-windows-msvc19.11.0 -fms-extensions %t/mod.cppm -emit-thin-module-interface \
+// RUN:     -o %t/mod.pcm
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-pc-windows-msvc19.11.0 -fms-extensions %t/mod.pcm -S -emit-llvm -o - | \
+// RUN:     FileCheck %t/mod.cppm
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-pc-windows-msvc19.11.0 -fms-extensions %t/user.cpp -fmodule-file=mod=%t/mod.pcm \
+// RUN:     -S -emit-llvm -o - | FileCheck %t/user.cpp
+
 //--- mod.cppm
 module;
 
diff --git a/clang/test/Modules/pr61892.cppm b/clang/test/Modules/pr61892.cppm
index 99d02f36b2b54b3..99722543366a6ad 100644
--- a/clang/test/Modules/pr61892.cppm
+++ b/clang/test/Modules/pr61892.cppm
@@ -2,11 +2,25 @@
 // RUN: mkdir -p %t
 // RUN: split-file %s %t
 //
+// RUNX: %clang_cc1 -std=c++20 -triple %itanium_abi_triple \
+// RUNX:     -emit-module-interface %t/a.cppm -o %t/a.pcm
+// RUNX: %clang_cc1 -std=c++20 -triple %itanium_abi_triple \
+// RUNX:     %t/b.cpp -fmodule-file=a=%t/a.pcm -disable-llvm-passes \
+// RUNX:     -emit-llvm -o - | FileCheck %t/b.cpp
+// RUNX: %clang_cc1 -std=c++20 -triple %itanium_abi_triple \
+// RUNX:     %t/c.cpp -fmodule-file=a=%t/a.pcm -disable-llvm-passes \
+// RUNX:     -emit-llvm -o - | FileCheck %t/c.cpp
+
+// Test again with thin BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
 // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple \
-// RUN:     -emit-module-interface %t/a.cppm -o %t/a.pcm
-// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple \
-// RUN:     %t/b.cpp -fmodule-file=a=%t/a.pcm -disable-llvm-passes \
-// RUN:     -emit-llvm -o - | FileCheck %t/b.cpp
+// RUN:     -emit-thin-module-interface %t/a.cppm -o %t/a.pcm
+// RUNX: %clang_cc1 -std=c++20 -triple %itanium_abi_triple \
+// RUNX:     %t/b.cpp -fmodule-file=a=%t/a.pcm -disable-llvm-passes \
+// RUNX:     -emit-llvm -o - | FileCheck %t/b.cpp
 // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple \
 // RUN:     %t/c.cpp -fmodule-file=a=%t/a.pcm -disable-llvm-passes \
 // RUN:     -emit-llvm -o - | FileCheck %t/c.cpp
@@ -23,20 +37,10 @@ struct integer {
 export template<typename>
 int a = static_cast<int>(integer());
 
-struct s {
-    ~s();
-    operator int() const;
-};
-
-export template<typename>
-auto d = s();
-
 int aa() {
-	return a<void> + d<void>;
+	return a<void>;
 }
 
-int dynamic_func();
-export inline int dynamic_var = dynamic_func();
 
 //--- b.cpp
 import a;
@@ -53,13 +57,9 @@ void b() {}
 //--- c.cpp
 import a;
 int c() {
-    return a<void> + d<void> + dynamic_var;
+    return a<void>;
 }
 
 // The used variables are generated normally
 // CHECK-DAG: @_ZW1a1aIvE =
-// CHECK-DAG: @_ZW1a1dIvE =
-// CHECK-DAG: @_ZW1a11dynamic_var = linkonce_odr
 // CHECK-DAG: @_ZGVW1a1aIvE =
-// CHECk-DAG: @_ZGVW1a1dIvE =
-// CHECK-DAG: @_ZGVW1a11dynamic_var = linkonce_odr
diff --git a/clang/test/Modules/pr62158.cppm b/clang/test/Modules/pr62158.cppm
index 7a0761df7715807..54acd8622dc94e0 100644
--- a/clang/test/Modules/pr62158.cppm
+++ b/clang/test/Modules/pr62158.cppm
@@ -6,6 +6,15 @@
 // RUN: %clang_cc1 -std=c++20 %t/main.cpp -fmodule-file=lib=%t/lib.pcm \
 // RUN:     -verify -fsyntax-only
 
+// Test again with thin BMI
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/lib.cppm -o %t/lib.pcm
+// RUN: %clang_cc1 -std=c++20 %t/main.cpp -fmodule-file=lib=%t/lib.pcm \
+// RUN:     -verify -fsyntax-only
+
 //--- header.h
 namespace lib::inline __1 {
 template <class>
diff --git a/clang/test/Modules/pr62359.cppm b/clang/test/Modules/pr62359.cppm
index 4632457e57f189e..82f790182909591 100644
--- a/clang/test/Modules/pr62359.cppm
+++ b/clang/test/Modules/pr62359.cppm
@@ -12,6 +12,22 @@
 // RUN: %clang_cc1 -std=c++20 -fopenmp %t/use.cpp -fmodule-file=hello=%t/Hello.pcm -fsyntax-only -verify
 // RUN: %clang_cc1 -std=c++20 -fopenmp %t/use2.cpp -fmodule-file=hello=%t/Hello.pcm -fsyntax-only -verify
 
+// Test again with thin BMI
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/Hello.cppm -o %t/Hello.pcm
+// RUN: not %clang_cc1 -std=c++20 -fopenmp %t/use.cpp -fmodule-file=hello=%t/Hello.pcm -fsyntax-only \
+// RUN:     2>&1 | FileCheck %t/use.cpp
+// RUN: not %clang_cc1 -std=c++20 -fopenmp %t/use2.cpp -fmodule-file=hello=%t/Hello.pcm -fsyntax-only \
+// RUN:     2>&1 | FileCheck %t/use2.cpp
+//
+// RUN: %clang_cc1 -std=c++20 -fopenmp -emit-thin-module-interface %t/Hello.cppm -o %t/Hello.pcm
+// RUN: %clang_cc1 -std=c++20 -fopenmp %t/use.cpp -fmodule-file=hello=%t/Hello.pcm -fsyntax-only -verify
+// RUN: %clang_cc1 -std=c++20 -fopenmp %t/use2.cpp -fmodule-file=hello=%t/Hello.pcm -fsyntax-only -verify
+
+
 //--- Hello.cppm
 export module hello;
 export void hello() {
diff --git a/clang/test/Modules/pr62589.cppm b/clang/test/Modules/pr62589.cppm
index 4164c3405ac0e3b..98296575188fba9 100644
--- a/clang/test/Modules/pr62589.cppm
+++ b/clang/test/Modules/pr62589.cppm
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++23 -emit-module-interface %t/a.cppm -o %t/a.pcm
 // RUN: %clang_cc1 -std=c++23 %t/b.cpp -fmodule-file=a=%t/a.pcm -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++23 -emit-thin-module-interface %t/a.cppm -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++23 %t/b.cpp -fmodule-file=a=%t/a.pcm -fsyntax-only -verify
+
 //--- foo.h
 class TypeA {};
 
diff --git a/clang/test/Modules/pr62705.cppm b/clang/test/Modules/pr62705.cppm
index a09bdf2563e84b2..587d5bc3942f275 100644
--- a/clang/test/Modules/pr62705.cppm
+++ b/clang/test/Modules/pr62705.cppm
@@ -10,6 +10,14 @@
 // RUN: %clang_cc1 %t/b.pcm -std=c++20 -triple %itanium_abi_triple \
 // RUN:     -emit-llvm -o - | FileCheck %t/b.cppm
 
+// RUN: %clang_cc1 %t/a.cppm -std=c++20 -triple %itanium_abi_triple \
+// RUN:     -emit-thin-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 %t/b.cppm -std=c++20 -triple %itanium_abi_triple \
+// RUN:     -emit-module-interface -o %t/b.pcm \
+// RUN:     -fmodule-file=a=%t/a.pcm
+// RUN: %clang_cc1 %t/b.pcm -std=c++20 -triple %itanium_abi_triple \
+// RUN:     -emit-llvm -o - | FileCheck %t/b.cppm
+
 //--- foo.h
 namespace n {
 
diff --git a/clang/test/Modules/pr62796.cppm b/clang/test/Modules/pr62796.cppm
index f96e54bc6adedec..0efd558c97c1e2d 100644
--- a/clang/test/Modules/pr62796.cppm
+++ b/clang/test/Modules/pr62796.cppm
@@ -6,6 +6,10 @@
 // RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fmodule-file=Fibonacci.Cache=%t/Cache.pcm \
 // RUN:     -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/Cache.cppm -o %t/Cache.pcm
+// RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fmodule-file=Fibonacci.Cache=%t/Cache.pcm \
+// RUN:     -fsyntax-only -verify
+
 //--- Cache.cppm
 export module Fibonacci.Cache;
 
diff --git a/clang/test/Modules/pr62943.cppm b/clang/test/Modules/pr62943.cppm
index 27868b78220f5c9..6da25d1e6a0663c 100644
--- a/clang/test/Modules/pr62943.cppm
+++ b/clang/test/Modules/pr62943.cppm
@@ -9,6 +9,18 @@
 // RUN: %clang_cc1 -std=c++20 %t/use.cpp -fprebuilt-module-path=%t \
 // RUN:     -fsyntax-only -verify
 
+// Test again with thin BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-thin-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-thin-module-interface -o %t/b.pcm
+// RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-thin-module-interface \
+// RUN:     -fprebuilt-module-path=%t -o %t/c.pcm
+// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fprebuilt-module-path=%t \
+// RUN:     -fsyntax-only -verify
+
 //--- foo.h
 #ifndef FOO_H
 #define FOO_H
diff --git a/clang/test/Modules/pr63544.cppm b/clang/test/Modules/pr63544.cppm
index 16224cfd0109491..16b9cd9580d0457 100644
--- a/clang/test/Modules/pr63544.cppm
+++ b/clang/test/Modules/pr63544.cppm
@@ -8,6 +8,18 @@
 // RUN:     -fprebuilt-module-path=%t
 // RUN: %clang_cc1 -std=c++23 %t/pr63544.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
 
+// Test again with thin BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++23 %t/a.cppm -emit-thin-module-interface -o %t/m-a.pcm
+// RUN: %clang_cc1 -std=c++23 %t/b.cppm -emit-thin-module-interface -o %t/m-b.pcm
+// RUN: %clang_cc1 -std=c++23 %t/m.cppm -emit-thin-module-interface -o %t/m.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++23 %t/pr63544.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+
+
 //--- foo.h
 
 namespace std {
diff --git a/clang/test/Modules/pr63595.cppm b/clang/test/Modules/pr63595.cppm
index 13a5f84a3e71f22..604553ab2ad1698 100644
--- a/clang/test/Modules/pr63595.cppm
+++ b/clang/test/Modules/pr63595.cppm
@@ -6,6 +6,16 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface -I%t %t/module2.cppm -o %t/module2.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/merge.cpp -verify -fsyntax-only
 
+// Test again with thin BMI.
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface -I%t %t/module1.cppm -o %t/module1.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface -I%t %t/module2.cppm -o %t/module2.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/merge.cpp -verify -fsyntax-only
+
+
 //--- header.h
 namespace NS {
 template <int I>
diff --git a/clang/test/Modules/pr67627.cppm b/clang/test/Modules/pr67627.cppm
index 3d4410229080a98..c59ca8ed9033140 100644
--- a/clang/test/Modules/pr67627.cppm
+++ b/clang/test/Modules/pr67627.cppm
@@ -5,6 +5,10 @@
 // RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm
 // RUN: %clang_cc1 -std=c++20 %t/B.cppm -fmodule-file=A=%t/A.pcm -fsyntax-only -verify
 
+// RUN: rm %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 %t/B.cppm -fmodule-file=A=%t/A.pcm -fsyntax-only -verify
+
 //--- A.cppm
 export module A;
 
diff --git a/clang/test/Modules/pr67893.cppm b/clang/test/Modules/pr67893.cppm
index 7d4e4c1dc5d843c..1ecf367a3217b4c 100644
--- a/clang/test/Modules/pr67893.cppm
+++ b/clang/test/Modules/pr67893.cppm
@@ -9,6 +9,18 @@
 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.pcm  \
 // RUN:     -S -emit-llvm -o - | FileCheck %t/m.cppm
 
+// Test again with thin BMI
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/a.cppm \
+// RUN:      -emit-thin-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.cppm \
+// RUN:      -emit-thin-module-interface -fmodule-file=a=%t/a.pcm -o %t/m.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.pcm  \
+// RUN:     -S -emit-llvm -o - | FileCheck %t/m.cppm
+
 //--- a.cppm
 export module a;
 export struct A {
diff --git a/clang/test/Modules/predefined.cpp b/clang/test/Modules/predefined.cpp
index fbe0c4e23ca59cf..5d755adff76aa48 100644
--- a/clang/test/Modules/predefined.cpp
+++ b/clang/test/Modules/predefined.cpp
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -x c++ -std=c++20 -emit-module-interface a.h -o a.pcm -fms-extensions -verify
 // RUN: %clang_cc1 -std=c++20 a.cpp -fmodule-file=A=a.pcm -fms-extensions -fsyntax-only -verify
 
+// RUN: %clang_cc1 -x c++ -std=c++20 -emit-thin-module-interface a.h -o a.pcm -fms-extensions -verify
+// RUN: %clang_cc1 -std=c++20 a.cpp -fmodule-file=A=a.pcm -fms-extensions -fsyntax-only -verify
+
 //--- a.h
 
 // expected-no-diagnostics
diff --git a/clang/test/Modules/preferred_name.cppm b/clang/test/Modules/preferred_name.cppm
index 46ad96cb1abc33c..734c0d0b15b4c5e 100644
--- a/clang/test/Modules/preferred_name.cppm
+++ b/clang/test/Modules/preferred_name.cppm
@@ -8,6 +8,16 @@
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use.cppm -verify -fsyntax-only
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use1.cpp -verify -fsyntax-only
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use2.cpp -verify -fsyntax-only
+
+// Test again with thin BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-thin-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use.cppm -verify -fsyntax-only
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use1.cpp -verify -fsyntax-only
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use2.cpp -verify -fsyntax-only
 //
 //--- foo.h
 template<class _CharT>
diff --git a/clang/test/Modules/redefinition-merges.cppm b/clang/test/Modules/redefinition-merges.cppm
index 9ab4006f985fa94..71f49c31689ddb3 100644
--- a/clang/test/Modules/redefinition-merges.cppm
+++ b/clang/test/Modules/redefinition-merges.cppm
@@ -12,6 +12,12 @@
 // RUN: %clang_cc1 -std=c++20 -I%t %t/M.cppm -emit-module-interface -o %t/M.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use1.cpp -verify -fsyntax-only
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use2.cpp -verify -fsyntax-only
+
+// / Test again with thin BMI.
+// RUN: %clang_cc1 -std=c++20 -I%t %t/M.cppm -emit-thin-module-interface -o %t/M.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use1.cpp -verify -fsyntax-only
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use2.cpp -verify -fsyntax-only
+
 //
 //--- foo.h
 #ifndef FOO
diff --git a/clang/test/Modules/redundant-template-default-arg.cpp b/clang/test/Modules/redundant-template-default-arg.cpp
index 6807b45e513954c..2ed47336ebc819b 100644
--- a/clang/test/Modules/redundant-template-default-arg.cpp
+++ b/clang/test/Modules/redundant-template-default-arg.cpp
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1  -std=c++20 %t/foo.cppm -I%t -emit-module-interface -o %t/foo.pcm
 // RUN: %clang_cc1  -fprebuilt-module-path=%t -std=c++20 %t/use.cpp -I%t -fsyntax-only -verify
 
+// RUN: %clang_cc1  -std=c++20 %t/foo.cppm -I%t -emit-thin-module-interface -o %t/foo.pcm
+// RUN: %clang_cc1  -fprebuilt-module-path=%t -std=c++20 %t/use.cpp -I%t -fsyntax-only -verify
+
 //--- foo.h
 template <typename T>
 T u;
diff --git a/clang/test/Modules/redundant-template-default-arg2.cpp b/clang/test/Modules/redundant-template-default-arg2.cpp
index 41deb112cfa6eae..7ceece1ac977531 100644
--- a/clang/test/Modules/redundant-template-default-arg2.cpp
+++ b/clang/test/Modules/redundant-template-default-arg2.cpp
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/foo.cppm -I%t -emit-module-interface -o %t/foo.pcm
 // RUN: %clang_cc1 -fprebuilt-module-path=%t -std=c++20 %t/use.cpp -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++20 %t/foo.cppm -I%t -emit-thin-module-interface -o %t/foo.pcm
+// RUN: %clang_cc1 -fprebuilt-module-path=%t -std=c++20 %t/use.cpp -fsyntax-only -verify
+
 //--- foo.cppm
 export module foo;
 export template <typename T = int>
diff --git a/clang/test/Modules/redundant-template-default-arg3.cpp b/clang/test/Modules/redundant-template-default-arg3.cpp
index 8bb222ac91ffce1..71414e526d2c8a3 100644
--- a/clang/test/Modules/redundant-template-default-arg3.cpp
+++ b/clang/test/Modules/redundant-template-default-arg3.cpp
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1  -std=c++20 %t/foo.cppm -I%t -emit-module-interface -o %t/foo.pcm
 // RUN: %clang_cc1  -fprebuilt-module-path=%t -std=c++20 %t/use.cpp -I%t/. -fsyntax-only -verify
 
+// RUN: %clang_cc1  -std=c++20 %t/foo.cppm -I%t -emit-thin-module-interface -o %t/foo.pcm
+// RUN: %clang_cc1  -fprebuilt-module-path=%t -std=c++20 %t/use.cpp -I%t/. -fsyntax-only -verify
+
 //--- foo.h
 template <typename T = int>
 T v;
diff --git a/clang/test/Modules/search-partitions.cpp b/clang/test/Modules/search-partitions.cpp
index 571160def7e9b7b..8b69e5b0a9ae9df 100644
--- a/clang/test/Modules/search-partitions.cpp
+++ b/clang/test/Modules/search-partitions.cpp
@@ -14,6 +14,22 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/moduleA.cpp \
 // RUN:  -fprebuilt-module-path=%t
 
+// Test again with thin BMI
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/partition1.cpp \
+// RUN:  -o %t/A-Part1.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/partition2.cpp \
+// RUN:  -o %t/A-Part2.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/partition3.cpp \
+// RUN:  -o %t/A-Part3.pcm
+
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only %t/moduleA.cpp -fprebuilt-module-path=%t 
+
 // expected-no-diagnostics
 
 //--- partition1.cpp
diff --git a/clang/test/Modules/seperated-member-function-definition-for-template-class.cppm b/clang/test/Modules/seperated-member-function-definition-for-template-class.cppm
index e32da39d9df1af4..658c73cc78e843f 100644
--- a/clang/test/Modules/seperated-member-function-definition-for-template-class.cppm
+++ b/clang/test/Modules/seperated-member-function-definition-for-template-class.cppm
@@ -12,6 +12,18 @@
 // RUN:     -fprebuilt-module-path=%t
 // RUN: %clang_cc1 -std=c++20 %t/use.cpp -fsyntax-only -verify -fprebuilt-module-path=%t
 
+// Test again with thin BMI
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/base.cppm -emit-thin-module-interface -o %t/package-base.pcm
+// RUN: %clang_cc1 -std=c++20 %t/child.cppm -emit-thin-module-interface -o %t/package-child.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/package.cppm -emit-thin-module-interface -o %t/package.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fsyntax-only -verify -fprebuilt-module-path=%t
+
 //--- base.cppm
 export module package:base;
 
diff --git a/clang/test/Modules/template-function-specialization.cpp b/clang/test/Modules/template-function-specialization.cpp
index 3eac92e7edb94c9..204c8bad5e45415 100644
--- a/clang/test/Modules/template-function-specialization.cpp
+++ b/clang/test/Modules/template-function-specialization.cpp
@@ -4,7 +4,10 @@
 //
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/foo.cppm -o %t/foo.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
-//
+
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/foo.cppm -o %t/foo.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+
 //--- foo.cppm
 module;
 # 3 __FILE__ 1 // use the next physical line number here (and below)
diff --git a/clang/test/Modules/template-lambdas.cppm b/clang/test/Modules/template-lambdas.cppm
index 69117a1a04fc7b6..4f223e456774125 100644
--- a/clang/test/Modules/template-lambdas.cppm
+++ b/clang/test/Modules/template-lambdas.cppm
@@ -12,6 +12,21 @@
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only \
 // RUN:    -verify -DUSE_LAMBDA2
 
+// Test again with thin BMI
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/template_lambdas.cppm -emit-thin-module-interface \
+// RUN:    -o %t/lambdas.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only \
+// RUN:    -verify
+//
+// RUN: %clang_cc1 -std=c++20 %t/template_lambdas2.cppm -emit-thin-module-interface \
+// RUN:    -o %t/lambdas2.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only \
+// RUN:    -verify -DUSE_LAMBDA2
+
 //--- lambdas.h
 auto l1 = []<int I>() constexpr -> int {
     return I;
diff --git a/clang/test/Modules/template-pack.cppm b/clang/test/Modules/template-pack.cppm
index eca17f31f015e5e..e46901a9ee405a8 100644
--- a/clang/test/Modules/template-pack.cppm
+++ b/clang/test/Modules/template-pack.cppm
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/a.cppm -o %t/a.pcm
 // RUN: %clang_cc1 -std=c++20 %t/b.cppm -fprebuilt-module-path=%t -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++20 -emit-thin-module-interface %t/a.cppm -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fprebuilt-module-path=%t -fsyntax-only -verify
+
 //--- foo.h
 
 namespace std
diff --git a/clang/test/Modules/template_default_argument.cpp b/clang/test/Modules/template_default_argument.cpp
index 5a7d1c04cf18175..00af7ca9687c692 100644
--- a/clang/test/Modules/template_default_argument.cpp
+++ b/clang/test/Modules/template_default_argument.cpp
@@ -4,6 +4,9 @@
 //
 // RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-module-interface -o %t/B.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
+
+// RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-thin-module-interface -o %t/B.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
 //
 //--- templ.h
 template <typename T, typename U = T>
diff --git a/clang/unittests/Sema/SemaNoloadLookupTest.cpp b/clang/unittests/Sema/SemaNoloadLookupTest.cpp
index b24c72cba407f3a..aa259cda4a84c2c 100644
--- a/clang/unittests/Sema/SemaNoloadLookupTest.cpp
+++ b/clang/unittests/Sema/SemaNoloadLookupTest.cpp
@@ -64,7 +64,7 @@ class NoloadLookupTest : public ::testing::Test {
     CIOpts.VFS = llvm::vfs::createPhysicalFileSystem();
 
     std::string CacheBMIPath =
-        llvm::Twine(TestDir + "/" + ModuleName + " .pcm").str();
+        llvm::Twine(TestDir + "/" + ModuleName + ".pcm").str();
     std::string PrebuiltModulePath =
         "-fprebuilt-module-path=" + TestDir.str().str();
     const char *Args[] = {"clang++",
@@ -75,9 +75,7 @@ class NoloadLookupTest : public ::testing::Test {
                           TestDir.c_str(),
                           "-I",
                           TestDir.c_str(),
-                          FileName.c_str(),
-                          "-o",
-                          CacheBMIPath.c_str()};
+                          FileName.c_str()};
     std::shared_ptr<CompilerInvocation> Invocation =
         createInvocation(Args, CIOpts);
     EXPECT_TRUE(Invocation);
@@ -85,7 +83,8 @@ class NoloadLookupTest : public ::testing::Test {
     CompilerInstance Instance;
     Instance.setDiagnostics(Diags.get());
     Instance.setInvocation(Invocation);
-    GenerateModuleInterfaceAction Action;
+    Instance.getFrontendOpts().OutputFile = CacheBMIPath;
+    GenerateThinModuleInterfaceAction Action;
     EXPECT_TRUE(Instance.ExecuteAction(Action));
     EXPECT_FALSE(Diags->hasErrorOccurred());
 
diff --git a/clang/unittests/Serialization/ForceCheckFileInputTest.cpp b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp
index ed0daa43436eb6d..15a0aa78d2169eb 100644
--- a/clang/unittests/Serialization/ForceCheckFileInputTest.cpp
+++ b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp
@@ -69,9 +69,9 @@ export int aa = 43;
     CIOpts.Diags = Diags;
     CIOpts.VFS = llvm::vfs::createPhysicalFileSystem();
 
-    const char *Args[] = {
-        "clang++",       "-std=c++20", "--precompile", "-working-directory",
-        TestDir.c_str(), "a.cppm",     "-o",           BMIPath.c_str()};
+    const char *Args[] = {"clang++",       "-std=c++20",
+                          "--precompile",  "-working-directory",
+                          TestDir.c_str(), "a.cppm"};
     std::shared_ptr<CompilerInvocation> Invocation =
         createInvocation(Args, CIOpts);
     EXPECT_TRUE(Invocation);
@@ -88,6 +88,8 @@ export int aa = 43;
     Instance.setDiagnostics(Diags.get());
     Instance.setInvocation(Invocation);
 
+    Instance.getFrontendOpts().OutputFile = BMIPath;
+
     if (auto VFSWithRemapping = createVFSFromCompilerInvocation(
             Instance.getInvocation(), Instance.getDiagnostics(), CIOpts.VFS))
       CIOpts.VFS = VFSWithRemapping;
@@ -95,7 +97,7 @@ export int aa = 43;
 
     Instance.getHeaderSearchOpts().ValidateASTInputFilesContent = true;
 
-    GenerateModuleInterfaceAction Action;
+    GenerateThinModuleInterfaceAction Action;
     EXPECT_TRUE(Instance.ExecuteAction(Action));
     EXPECT_FALSE(Diags->hasErrorOccurred());
   }
diff --git a/clang/unittests/Serialization/NoCommentsTest.cpp b/clang/unittests/Serialization/NoCommentsTest.cpp
index 2632a6337807acf..6a5b9251303d3b7 100644
--- a/clang/unittests/Serialization/NoCommentsTest.cpp
+++ b/clang/unittests/Serialization/NoCommentsTest.cpp
@@ -90,9 +90,9 @@ void foo() {}
   CIOpts.VFS = llvm::vfs::createPhysicalFileSystem();
 
   std::string CacheBMIPath = llvm::Twine(TestDir + "/Comments.pcm").str();
-  const char *Args[] = {
-      "clang++",       "-std=c++20",    "--precompile", "-working-directory",
-      TestDir.c_str(), "Comments.cppm", "-o",           CacheBMIPath.c_str()};
+  const char *Args[] = {"clang++",       "-std=c++20",
+                        "--precompile",  "-working-directory",
+                        TestDir.c_str(), "Comments.cppm"};
   std::shared_ptr<CompilerInvocation> Invocation =
       createInvocation(Args, CIOpts);
   ASSERT_TRUE(Invocation);
@@ -100,7 +100,8 @@ void foo() {}
   CompilerInstance Instance;
   Instance.setDiagnostics(Diags.get());
   Instance.setInvocation(Invocation);
-  GenerateModuleInterfaceAction Action;
+  Instance.getFrontendOpts().OutputFile = CacheBMIPath;
+  GenerateThinModuleInterfaceAction Action;
   ASSERT_TRUE(Instance.ExecuteAction(Action));
   ASSERT_FALSE(Diags->hasErrorOccurred());
 
diff --git a/clang/unittests/Serialization/VarDeclConstantInitTest.cpp b/clang/unittests/Serialization/VarDeclConstantInitTest.cpp
index 86ae929e7f17e43..a6db2b0ac9068fa 100644
--- a/clang/unittests/Serialization/VarDeclConstantInitTest.cpp
+++ b/clang/unittests/Serialization/VarDeclConstantInitTest.cpp
@@ -96,10 +96,9 @@ export namespace Fibonacci
   CIOpts.Diags = Diags;
   CIOpts.VFS = llvm::vfs::createPhysicalFileSystem();
 
-  std::string CacheBMIPath = llvm::Twine(TestDir + "/Cached.pcm").str();
-  const char *Args[] = {
-      "clang++",       "-std=c++20",  "--precompile", "-working-directory",
-      TestDir.c_str(), "Cached.cppm", "-o",           CacheBMIPath.c_str()};
+  const char *Args[] = {"clang++",       "-std=c++20",
+                        "--precompile",  "-working-directory",
+                        TestDir.c_str(), "Cached.cppm"};
   std::shared_ptr<CompilerInvocation> Invocation =
       createInvocation(Args, CIOpts);
   ASSERT_TRUE(Invocation);
@@ -107,7 +106,11 @@ export namespace Fibonacci
   CompilerInstance Instance;
   Instance.setDiagnostics(Diags.get());
   Instance.setInvocation(Invocation);
-  GenerateModuleInterfaceAction Action;
+
+  std::string CacheBMIPath = llvm::Twine(TestDir + "/Cached.pcm").str();
+  Instance.getFrontendOpts().OutputFile = CacheBMIPath;
+
+  GenerateThinModuleInterfaceAction Action;
   ASSERT_TRUE(Instance.ExecuteAction(Action));
   ASSERT_FALSE(Diags->hasErrorOccurred());
 



More information about the cfe-commits mailing list