https://github.com/aengelke updated 
https://github.com/llvm/llvm-project/pull/173868

>From 684214fc7faf2af988577533563bf4370730ce71 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <[email protected]>
Date: Tue, 30 Dec 2025 10:15:51 +0000
Subject: [PATCH 01/12] [LLD][MachO] Avoid ambiguity between lld::Reloc and
 llvm::Reloc

---
 lld/MachO/EhFrame.cpp           | 15 +++++------
 lld/MachO/ICF.cpp               | 18 ++++++-------
 lld/MachO/InputSection.cpp      | 15 +++++------
 lld/MachO/ObjC.cpp              | 46 +++++++++++++++++----------------
 lld/MachO/Relocations.cpp       |  1 -
 lld/MachO/UnwindInfoSection.cpp | 19 +++++++-------
 6 files changed, 56 insertions(+), 58 deletions(-)

diff --git a/lld/MachO/EhFrame.cpp b/lld/MachO/EhFrame.cpp
index 2446b49b5098a..e6b473475c1fe 100644
--- a/lld/MachO/EhFrame.cpp
+++ b/lld/MachO/EhFrame.cpp
@@ -13,7 +13,6 @@
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/Support/Endian.h"
 
-using namespace llvm;
 using namespace lld;
 using namespace lld::macho;
 using namespace llvm::support::endian;
@@ -24,7 +23,7 @@ uint64_t EhReader::readLength(size_t *off) const {
     failOn(errOff, "CIE/FDE too small");
   uint64_t len = read32le(data.data() + *off);
   *off += 4;
-  if (len == dwarf::DW_LENGTH_DWARF64) {
+  if (len == llvm::dwarf::DW_LENGTH_DWARF64) {
     // FIXME: test this DWARF64 code path
     if (*off + 8 > data.size())
       failOn(errOff, "CIE/FDE too small");
@@ -39,7 +38,7 @@ uint64_t EhReader::readLength(size_t *off) const {
 void EhReader::skipValidLength(size_t *off) const {
   uint32_t len = read32le(data.data() + *off);
   *off += 4;
-  if (len == dwarf::DW_LENGTH_DWARF64)
+  if (len == llvm::dwarf::DW_LENGTH_DWARF64)
     *off += 8;
 }
 
@@ -106,10 +105,10 @@ void EhReader::failOn(size_t errOff, const Twine &msg) 
const {
  *   `(a + offset) - b` if Invert == true
  */
 template <bool Invert = false>
-static void createSubtraction(PointerUnion<Symbol *, InputSection *> a,
-                              PointerUnion<Symbol *, InputSection *> b,
+static void createSubtraction(llvm::PointerUnion<Symbol *, InputSection *> a,
+                              llvm::PointerUnion<Symbol *, InputSection *> b,
                               uint64_t off, uint8_t length,
-                              SmallVectorImpl<Reloc> *newRelocs) {
+                              llvm::SmallVectorImpl<Reloc> *newRelocs) {
   auto subtrahend = a;
   auto minuend = b;
   if (Invert)
@@ -124,13 +123,13 @@ static void createSubtraction(PointerUnion<Symbol *, 
InputSection *> a,
 }
 
 void EhRelocator::makePcRel(uint64_t off,
-                            PointerUnion<Symbol *, InputSection *> target,
+                            llvm::PointerUnion<Symbol *, InputSection *> 
target,
                             uint8_t length) {
   createSubtraction(isec->symbols[0], target, off, length, &newRelocs);
 }
 
 void EhRelocator::makeNegativePcRel(
-    uint64_t off, PointerUnion<Symbol *, InputSection *> target,
+    uint64_t off, llvm::PointerUnion<Symbol *, InputSection *> target,
     uint8_t length) {
   createSubtraction</*Invert=*/true>(isec, target, off, length, &newRelocs);
 }
diff --git a/lld/MachO/ICF.cpp b/lld/MachO/ICF.cpp
index e0fc89782a419..aae5dfa1b03a4 100644
--- a/lld/MachO/ICF.cpp
+++ b/lld/MachO/ICF.cpp
@@ -20,7 +20,6 @@
 
 #include <atomic>
 
-using namespace llvm;
 using namespace lld;
 using namespace lld::macho;
 
@@ -374,10 +373,10 @@ void ICF::forEachClass(llvm::function_ref<void(size_t, 
size_t)> func) {
   size_t boundaries[shards + 1];
   boundaries[0] = 0;
   boundaries[shards] = icfInputs.size();
-  parallelFor(1, shards, [&](size_t i) {
+  llvm::parallelFor(1, shards, [&](size_t i) {
     boundaries[i] = findBoundary((i - 1) * step, icfInputs.size());
   });
-  parallelFor(1, shards + 1, [&](size_t i) {
+  llvm::parallelFor(1, shards + 1, [&](size_t i) {
     if (boundaries[i - 1] < boundaries[i]) {
       forEachClassRange(boundaries[i - 1], boundaries[i], func);
     }
@@ -388,7 +387,7 @@ void ICF::forEachClass(llvm::function_ref<void(size_t, 
size_t)> func) {
 void ICF::run() {
   // Into each origin-section hash, combine all reloc referent section hashes.
   for (icfPass = 0; icfPass < 2; ++icfPass) {
-    parallelForEach(icfInputs, [&](ConcatInputSection *isec) {
+    llvm::parallelForEach(icfInputs, [&](ConcatInputSection *isec) {
       uint32_t hash = isec->icfEqClass[icfPass % 2];
       for (const Reloc &r : isec->relocs) {
         if (auto *sym = r.referent.dyn_cast<Symbol *>()) {
@@ -507,7 +506,7 @@ void macho::markSymAsAddrSig(Symbol *s) {
 }
 
 void macho::markAddrSigSymbols() {
-  TimeTraceScope timeScope("Mark addrsig symbols");
+  llvm::TimeTraceScope timeScope("Mark addrsig symbols");
   for (InputFile *file : inputFiles) {
     ObjFile *obj = dyn_cast<ObjFile>(file);
     if (!obj)
@@ -550,7 +549,7 @@ Defined *macho::getBodyForThunkFoldedSym(Defined 
*foldedSym) {
   return cast<Defined>(targetSym);
 }
 void macho::foldIdenticalSections(bool onlyCfStrings) {
-  TimeTraceScope timeScope("Fold Identical Code Sections");
+  llvm::TimeTraceScope timeScope("Fold Identical Code Sections");
   // The ICF equivalence-class segregation algorithm relies on pre-computed
   // hashes of InputSection::data for the ConcatOutputSection::inputs and all
   // sections referenced by their relocs. We could recursively traverse the
@@ -575,8 +574,9 @@ void macho::foldIdenticalSections(bool onlyCfStrings) {
                                         isSelRefsSection(isec);
     // NOTE: __objc_selrefs is typically marked as no_dead_strip by MC, but we
     // can still fold it.
-    bool hasFoldableFlags = (isSelRefsSection(isec) ||
-                             sectionType(isec->getFlags()) == 
MachO::S_REGULAR);
+    bool hasFoldableFlags =
+        (isSelRefsSection(isec) ||
+         sectionType(isec->getFlags()) == llvm::MachO::S_REGULAR);
 
     bool isCodeSec = isCodeSection(isec);
 
@@ -620,7 +620,7 @@ void macho::foldIdenticalSections(bool onlyCfStrings) {
       isec->icfEqClass[0] = ++icfUniqueID;
     }
   }
-  parallelForEach(foldable, [](ConcatInputSection *isec) {
+  llvm::parallelForEach(foldable, [](ConcatInputSection *isec) {
     assert(isec->icfEqClass[0] == 0); // don't overwrite a unique ID!
     // Turn-on the top bit to guarantee that valid hashes have no collisions
     // with the small-integer unique IDs for ICF-ineligible sections
diff --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp
index 2b2d28ef63e2d..81ec37ace93d2 100644
--- a/lld/MachO/InputSection.cpp
+++ b/lld/MachO/InputSection.cpp
@@ -21,7 +21,6 @@
 #include "lld/Common/Memory.h"
 #include "llvm/Support/xxhash.h"
 
-using namespace llvm;
 using namespace llvm::MachO;
 using namespace llvm::support;
 using namespace lld;
@@ -146,7 +145,7 @@ std::string InputSection::getSourceLocation(uint64_t off) 
const {
   }
 
   auto createMsg = [&](StringRef path, unsigned line) {
-    std::string filename = sys::path::filename(path).str();
+    std::string filename = llvm::sys::path::filename(path).str();
     std::string lineStr = (":" + Twine(line)).str();
     if (filename == path)
       return filename + lineStr;
@@ -154,8 +153,8 @@ std::string InputSection::getSourceLocation(uint64_t off) 
const {
   };
 
   // First, look up a function for a given offset.
-  if (std::optional<DILineInfo> li = dwarf->getDILineInfo(
-          section.addr + off, object::SectionedAddress::UndefSection))
+  if (std::optional<llvm::DILineInfo> li = dwarf->getDILineInfo(
+          section.addr + off, llvm::object::SectionedAddress::UndefSection))
     return createMsg(li->FileName, li->Line);
 
   // If it failed, look up again as a variable.
@@ -302,8 +301,8 @@ StringPiece &CStringInputSection::getStringPiece(uint64_t 
off) {
   if (off >= data.size())
     fatal(toString(this) + ": offset is outside the section");
 
-  auto it =
-      partition_point(pieces, [=](StringPiece p) { return p.inSecOff <= off; 
});
+  auto it = llvm::partition_point(
+      pieces, [=](StringPiece p) { return p.inSecOff <= off; });
   return it[-1];
 }
 
@@ -315,8 +314,8 @@ size_t CStringInputSection::getStringPieceIndex(uint64_t 
off) const {
   if (off >= data.size())
     fatal(toString(this) + ": offset is outside the section");
 
-  auto it =
-      partition_point(pieces, [=](StringPiece p) { return p.inSecOff <= off; 
});
+  auto it = llvm::partition_point(
+      pieces, [=](StringPiece p) { return p.inSecOff <= off; });
   return std::distance(pieces.begin(), it) - 1;
 }
 
diff --git a/lld/MachO/ObjC.cpp b/lld/MachO/ObjC.cpp
index ab7f73c3a1df6..3ac27279905a7 100644
--- a/lld/MachO/ObjC.cpp
+++ b/lld/MachO/ObjC.cpp
@@ -17,10 +17,10 @@
 
 #include "lld/Common/ErrorHandler.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/Bitcode/BitcodeReader.h"
 #include "llvm/Support/TimeProfiler.h"
 
-using namespace llvm;
 using namespace llvm::MachO;
 using namespace lld;
 using namespace lld::macho;
@@ -38,10 +38,11 @@ template <class LP> static bool 
objectHasObjCSection(MemoryBufferRef mb) {
     auto sectionHeaders = ArrayRef<SectionHeader>{
         reinterpret_cast<const SectionHeader *>(c + 1), c->nsects};
     for (const SectionHeader &secHead : sectionHeaders) {
-      StringRef sectname(secHead.sectname,
-                         strnlen(secHead.sectname, sizeof(secHead.sectname)));
-      StringRef segname(secHead.segname,
-                        strnlen(secHead.segname, sizeof(secHead.segname)));
+      llvm::StringRef sectname(
+          secHead.sectname,
+          strnlen(secHead.sectname, sizeof(secHead.sectname)));
+      llvm::StringRef segname(
+          secHead.segname, strnlen(secHead.segname, sizeof(secHead.segname)));
       if ((segname == segment_names::data &&
            sectname == section_names::objcCatList) ||
           (segname == segment_names::text &&
@@ -62,9 +63,9 @@ static bool objectHasObjCSection(MemoryBufferRef mb) {
 
 bool macho::hasObjCSection(MemoryBufferRef mb) {
   switch (identify_magic(mb.getBuffer())) {
-  case file_magic::macho_object:
+  case llvm::file_magic::macho_object:
     return objectHasObjCSection(mb);
-  case file_magic::bitcode:
+  case llvm::file_magic::bitcode:
     return check(isBitcodeContainingObjCCategory(mb));
   default:
     return false;
@@ -153,8 +154,8 @@ enum MethodKind {
 };
 
 struct ObjcClass {
-  DenseMap<CachedHashStringRef, MethodContainer> instanceMethods;
-  DenseMap<CachedHashStringRef, MethodContainer> classMethods;
+  llvm::DenseMap<llvm::CachedHashStringRef, MethodContainer> instanceMethods;
+  llvm::DenseMap<llvm::CachedHashStringRef, MethodContainer> classMethods;
 };
 
 } // namespace
@@ -177,7 +178,7 @@ class ObjcCategoryChecker {
   ListHeaderLayout listHeaderLayout;
   MethodLayout methodLayout;
 
-  DenseMap<const Symbol *, ObjcClass> classMap;
+  llvm::DenseMap<const Symbol *, ObjcClass> classMap;
 };
 
 ObjcCategoryChecker::ObjcCategoryChecker()
@@ -196,7 +197,7 @@ void ObjcCategoryChecker::parseMethods(const 
ConcatInputSection *methodsIsec,
         methodLayout.nameOffset)
       continue;
 
-    CachedHashStringRef methodName(r.getReferentString());
+    llvm::CachedHashStringRef methodName(r.getReferentString());
     // +load methods are special: all implementations are called by the runtime
     // even if they are part of the same class. Thus there is no need to check
     // for duplicates.
@@ -311,7 +312,7 @@ void ObjcCategoryChecker::parseClass(const Defined 
*classSym) {
 }
 
 void objc::checkCategories() {
-  TimeTraceScope timeScope("ObjcCategoryChecker");
+  llvm::TimeTraceScope timeScope("ObjcCategoryChecker");
 
   ObjcCategoryChecker checker;
   for (const InputSection *isec : inputSections) {
@@ -420,7 +421,7 @@ class ObjcCategoryMerger {
   static void doCleanup();
 
 private:
-  DenseSet<const Symbol *> collectNlCategories();
+  llvm::DenseSet<const Symbol *> collectNlCategories();
   void collectAndValidateCategoriesData();
   bool
   mergeCategoriesIntoSingleCategory(std::vector<InfoInputCategory> 
&categories);
@@ -429,7 +430,7 @@ class ObjcCategoryMerger {
   void eraseMergedCategories();
 
   void generateCatListForNonErasedCategories(
-      MapVector<ConcatInputSection *, std::set<uint64_t>>
+      llvm::MapVector<ConcatInputSection *, std::set<uint64_t>>
           catListToErasedOffsets);
   void collectSectionWriteInfoFromIsec(const InputSection *isec,
                                        InfoWriteSection &catWriteInfo);
@@ -494,14 +495,14 @@ class ObjcCategoryMerger {
   InfoCategoryWriter infoCategoryWriter;
   std::vector<ConcatInputSection *> &allInputSections;
   // Map of base class Symbol to list of InfoInputCategory's for it
-  MapVector<const Symbol *, std::vector<InfoInputCategory>> categoryMap;
+  llvm::MapVector<const Symbol *, std::vector<InfoInputCategory>> categoryMap;
 
   // Normally, the binary data comes from the input files, but since we're
   // generating binary data ourselves, we use the below array to store it in.
   // Need this to be 'static' so the data survives past the ObjcCategoryMerger
   // object, as the data will be read by the Writer when the final binary is
   // generated.
-  static SmallVector<std::unique_ptr<SmallVector<uint8_t>>>
+  static llvm::SmallVector<std::unique_ptr<llvm::SmallVector<uint8_t>>>
       generatedSectionData;
 };
 
@@ -542,7 +543,7 @@ ObjcCategoryMerger::tryGetSymbolAtIsecOffset(const 
ConcatInputSection *isec,
   if (!reloc)
     return nullptr;
 
-  Symbol *sym = dyn_cast_if_present<Symbol *>(reloc->referent);
+  Symbol *sym = llvm::dyn_cast_if_present<Symbol *>(reloc->referent);
 
   if (reloc->addend && sym) {
     assert(isa<Defined>(sym) && "Expected defined for non-zero addend");
@@ -1149,8 +1150,8 @@ void ObjcCategoryMerger::createSymbolReference(Defined 
*refFrom,
 // Get the list of categories in the '__objc_nlcatlist' section. We can't
 // optimize these as they have a '+load' method that has to be called at
 // runtime.
-DenseSet<const Symbol *> ObjcCategoryMerger::collectNlCategories() {
-  DenseSet<const Symbol *> nlCategories;
+llvm::DenseSet<const Symbol *> ObjcCategoryMerger::collectNlCategories() {
+  llvm::DenseSet<const Symbol *> nlCategories;
 
   for (InputSection *sec : allInputSections) {
     if (sec->getName() != section_names::objcNonLazyCatList)
@@ -1219,7 +1220,7 @@ void 
ObjcCategoryMerger::collectAndValidateCategoriesData() {
 // (not erased). For these not erased categories, we generate new 
__objc_catlist
 // entries since the parent __objc_catlist entry will be erased
 void ObjcCategoryMerger::generateCatListForNonErasedCategories(
-    const MapVector<ConcatInputSection *, std::set<uint64_t>>
+    const llvm::MapVector<ConcatInputSection *, std::set<uint64_t>>
         catListToErasedOffsets) {
 
   // Go through all offsets of all __objc_catlist's that we process and if 
there
@@ -1284,7 +1285,8 @@ void ObjcCategoryMerger::eraseISec(ConcatInputSection 
*isec) {
 // them.
 void ObjcCategoryMerger::eraseMergedCategories() {
   // Map of InputSection to a set of offsets of the categories that were merged
-  MapVector<ConcatInputSection *, std::set<uint64_t>> catListToErasedOffsets;
+  llvm::MapVector<ConcatInputSection *, std::set<uint64_t>>
+      catListToErasedOffsets;
 
   for (auto &mapEntry : categoryMap) {
     for (InfoInputCategory &catInfo : mapEntry.second) {
@@ -1374,7 +1376,7 @@ SmallVector<uint8_t> 
&ObjcCategoryMerger::newSectionData(uint32_t size) {
 } // namespace
 
 void objc::mergeCategories() {
-  TimeTraceScope timeScope("ObjcCategoryMerger");
+  llvm::TimeTraceScope timeScope("ObjcCategoryMerger");
 
   ObjcCategoryMerger merger(inputSections);
   merger.doMerge();
diff --git a/lld/MachO/Relocations.cpp b/lld/MachO/Relocations.cpp
index 78cc13388d6eb..f9b18305b5654 100644
--- a/lld/MachO/Relocations.cpp
+++ b/lld/MachO/Relocations.cpp
@@ -14,7 +14,6 @@
 
 #include "lld/Common/ErrorHandler.h"
 
-using namespace llvm;
 using namespace lld;
 using namespace lld::macho;
 
diff --git a/lld/MachO/UnwindInfoSection.cpp b/lld/MachO/UnwindInfoSection.cpp
index bf01b12d11dfd..0d6a829cf21dc 100644
--- a/lld/MachO/UnwindInfoSection.cpp
+++ b/lld/MachO/UnwindInfoSection.cpp
@@ -27,7 +27,6 @@
 
 #include <numeric>
 
-using namespace llvm;
 using namespace llvm::MachO;
 using namespace llvm::support::endian;
 using namespace lld;
@@ -118,7 +117,7 @@ struct CompactUnwindEntry {
   InputSection *lsda;
 };
 
-using EncodingMap = DenseMap<compact_unwind_encoding_t, size_t>;
+using EncodingMap = llvm::DenseMap<compact_unwind_encoding_t, size_t>;
 
 struct SecondLevelPage {
   uint32_t kind;
@@ -146,7 +145,7 @@ class UnwindInfoSectionImpl final : public 
UnwindInfoSection {
   Symbol *canonicalizePersonality(Symbol *);
 
   uint64_t unwindInfoSize = 0;
-  SmallVector<decltype(symbols)::value_type, 0> symbolsVec;
+  llvm::SmallVector<decltype(symbols)::value_type, 0> symbolsVec;
   CompactUnwindLayout cuLayout;
   std::vector<std::pair<compact_unwind_encoding_t, size_t>> commonEncodings;
   EncodingMap commonEncodingIndexes;
@@ -154,12 +153,13 @@ class UnwindInfoSectionImpl final : public 
UnwindInfoSection {
   // in symbolsVec.
   std::vector<CompactUnwindEntry> cuEntries;
   std::vector<Symbol *> personalities;
-  SmallDenseMap<std::pair<InputSection *, uint64_t /* addend */>, Symbol *>
+  llvm::SmallDenseMap<std::pair<InputSection *, uint64_t /* addend */>,
+                      Symbol *>
       personalityTable;
   // Indices into cuEntries for CUEs with a non-null LSDA.
   std::vector<size_t> entriesWithLsda;
   // Map of cuEntries index to an index within the LSDA array.
-  DenseMap<size_t, uint32_t> lsdaIndex;
+  llvm::DenseMap<size_t, uint32_t> lsdaIndex;
   std::vector<SecondLevelPage> secondLevelPages;
   uint64_t level2PagesOffset = 0;
   // The highest-address function plus its size. The unwinder needs this to
@@ -346,7 +346,7 @@ Symbol 
*UnwindInfoSectionImpl::canonicalizePersonality(Symbol *personality) {
 // is no source address to make a relative location meaningful.
 void UnwindInfoSectionImpl::relocateCompactUnwind(
     std::vector<CompactUnwindEntry> &cuEntries) {
-  parallelFor(0, symbolsVec.size(), [&](size_t i) {
+  llvm::parallelFor(0, symbolsVec.size(), [&](size_t i) {
     CompactUnwindEntry &cu = cuEntries[i];
     const Defined *d = symbolsVec[i].second;
     cu.functionAddress = d->getVA();
@@ -383,9 +383,8 @@ void UnwindInfoSectionImpl::relocateCompactUnwind(
     auto buf =
         reinterpret_cast<const uint8_t *>(d->unwindEntry()->data.data()) -
         target->wordSize;
-    cu.functionLength =
-        support::endian::read32le(buf + cuLayout.functionLengthOffset);
-    cu.encoding = support::endian::read32le(buf + cuLayout.encodingOffset);
+    cu.functionLength = read32le(buf + cuLayout.functionLengthOffset);
+    cu.encoding = read32le(buf + cuLayout.encodingOffset);
     for (const Reloc &r : d->unwindEntry()->relocs) {
       if (r.offset == cuLayout.personalityOffset)
         cu.personality = cast<Symbol *>(r.referent);
@@ -402,7 +401,7 @@ void UnwindInfoSectionImpl::encodePersonalities() {
     if (cu.personality == nullptr)
       continue;
     // Linear search is fast enough for a small array.
-    auto it = find(personalities, cu.personality);
+    auto it = llvm::find(personalities, cu.personality);
     uint32_t personalityIndex; // 1-based index
     if (it != personalities.end()) {
       personalityIndex = std::distance(personalities.begin(), it) + 1;

>From 0132e36f56c9e3076b623d5bd8095c36581b53e1 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <[email protected]>
Date: Tue, 30 Dec 2025 12:07:07 +0000
Subject: [PATCH 02/12] [MLIR][NFC] Fix ambiguity between const char* and Twine

---
 mlir/lib/Support/TypeID.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/lib/Support/TypeID.cpp b/mlir/lib/Support/TypeID.cpp
index 304253cc6daa7..3526a0d49cc79 100644
--- a/mlir/lib/Support/TypeID.cpp
+++ b/mlir/lib/Support/TypeID.cpp
@@ -49,7 +49,7 @@ struct ImplicitTypeIDRegistry {
                    "`MLIR_DEFINE_EXPLICIT_TYPE_ID` or "
                    "`MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID`.\n";
       }
-      llvm::report_fatal_error(errorStr);
+      llvm::report_fatal_error(llvm::StringRef(errorStr));
     }
 #endif
 

>From 2fbd73f57cd15ce0d2d9f108414db862de979466 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <[email protected]>
Date: Wed, 7 Jan 2026 12:57:26 +0000
Subject: [PATCH 03/12] [CMake][LLVM] Add PCH infrastructure and LLVMSupport
 PCH

---
 clang/tools/c-index-test/CMakeLists.txt       |   2 +
 .../clang-fuzzer/dictionary/CMakeLists.txt    |   2 +
 flang/CMakeLists.txt                          |  10 --
 flang/lib/Evaluate/CMakeLists.txt             |  18 +--
 flang/lib/Frontend/CMakeLists.txt             |  16 +--
 flang/lib/Lower/CMakeLists.txt                |  22 +--
 flang/lib/Parser/CMakeLists.txt               |  16 +--
 flang/lib/Semantics/CMakeLists.txt            |  18 +--
 llvm/cmake/modules/AddLLVM.cmake              |  86 ++++++++++--
 llvm/cmake/modules/HandleLLVMOptions.cmake    |  10 ++
 .../CMakeLists.txt                            |   2 +
 .../OrcV2CBindingsBasicUsage/CMakeLists.txt   |   2 +
 .../OrcV2CBindingsDumpObjects/CMakeLists.txt  |   2 +
 .../OrcV2CBindingsIRTransforms/CMakeLists.txt |   2 +
 .../OrcV2CBindingsLazy/CMakeLists.txt         |   2 +
 .../CMakeLists.txt                            |   2 +
 .../CMakeLists.txt                            |   2 +
 .../OrcV2CBindingsVeryLazy/CMakeLists.txt     |   2 +
 llvm/include/llvm/Support/pch.h               | 130 ++++++++++++++++++
 llvm/lib/CMakeLists.txt                       |   2 +-
 llvm/lib/Support/CMakeLists.txt               |   7 +-
 llvm/tools/llvm-c-test/CMakeLists.txt         |   2 +
 llvm/utils/count/CMakeLists.txt               |   2 +
 mlir/test/CAPI/CMakeLists.txt                 |   1 +
 24 files changed, 295 insertions(+), 65 deletions(-)
 create mode 100644 llvm/include/llvm/Support/pch.h

diff --git a/clang/tools/c-index-test/CMakeLists.txt 
b/clang/tools/c-index-test/CMakeLists.txt
index 41e80e66ffa7a..2bbd387d6e812 100644
--- a/clang/tools/c-index-test/CMakeLists.txt
+++ b/clang/tools/c-index-test/CMakeLists.txt
@@ -5,6 +5,8 @@ set(LLVM_LINK_COMPONENTS
 add_clang_executable(c-index-test
   c-index-test.c
   core_main.cpp
+
+  DISABLE_PCH_REUSE # Prevent CMake error with C source files.
   )
 
 if(NOT MSVC)
diff --git a/clang/tools/clang-fuzzer/dictionary/CMakeLists.txt 
b/clang/tools/clang-fuzzer/dictionary/CMakeLists.txt
index 6b72b98f5e1c4..a7f18965b4e29 100644
--- a/clang/tools/clang-fuzzer/dictionary/CMakeLists.txt
+++ b/clang/tools/clang-fuzzer/dictionary/CMakeLists.txt
@@ -1,5 +1,7 @@
 set(CMAKE_CXX_FLAGS ${CXX_FLAGS_NOFUZZ})
 add_clang_executable(clang-fuzzer-dictionary
   dictionary.c
+
+  DISABLE_PCH_REUSE # no C++ files, prevent CMake error.
   )
 
diff --git a/flang/CMakeLists.txt b/flang/CMakeLists.txt
index c01eb56d5e496..e21304d2e4da7 100644
--- a/flang/CMakeLists.txt
+++ b/flang/CMakeLists.txt
@@ -441,11 +441,6 @@ if (LLVM_COMPILER_IS_GCC_COMPATIBLE)
   if (BUILD_SHARED_LIBS AND NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} 
-fno-semantic-interposition")
   endif()
-
-  # GCC requires this flag in order for precompiled headers to work with ccache
-  if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT 
CMAKE_DISABLE_PRECOMPILE_HEADERS)
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpch-preprocess")
-  endif()
 endif()
 
 # Clang on Darwin enables non-POSIX extensions by default, which allows the
@@ -456,11 +451,6 @@ if (APPLE)
   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_POSIX_C_SOURCE=200809")
 endif()
 
-# Clang requires this flag in order for precompiled headers to work with ccache
-if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT 
CMAKE_DISABLE_PRECOMPILE_HEADERS)
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Xclang -fno-pch-timestamp")
-endif()
-
 list(REMOVE_DUPLICATES CMAKE_CXX_FLAGS)
 
 # Determine HOST_LINK_VERSION on Darwin.
diff --git a/flang/lib/Evaluate/CMakeLists.txt 
b/flang/lib/Evaluate/CMakeLists.txt
index 24a1c9004bc3b..472ecb6d8d079 100644
--- a/flang/lib/Evaluate/CMakeLists.txt
+++ b/flang/lib/Evaluate/CMakeLists.txt
@@ -66,15 +66,8 @@ add_flang_library(FortranEvaluate
   ${LIBPGMATH}
   ${QUADMATHLIB}
 
-  LINK_COMPONENTS
-  Support
-
-  DEPENDS
-  acc_gen
-  omp_gen
-)
-
-target_precompile_headers(FortranEvaluate PRIVATE
+  DISABLE_PCH_REUSE
+  PRECOMPILE_HEADERS
   [["flang/Evaluate/common.h"]]
   [["flang/Evaluate/call.h"]]
   [["flang/Evaluate/traverse.h"]]
@@ -86,4 +79,11 @@ target_precompile_headers(FortranEvaluate PRIVATE
   [["flang/Evaluate/integer.h"]]
   [["flang/Evaluate/expression.h"]]
   [["flang/Evaluate/tools.h"]]
+
+  LINK_COMPONENTS
+  Support
+
+  DEPENDS
+  acc_gen
+  omp_gen
 )
diff --git a/flang/lib/Frontend/CMakeLists.txt 
b/flang/lib/Frontend/CMakeLists.txt
index 4ebe497e65676..bd67ec444f358 100644
--- a/flang/lib/Frontend/CMakeLists.txt
+++ b/flang/lib/Frontend/CMakeLists.txt
@@ -13,6 +13,14 @@ add_flang_library(flangFrontend
   TextDiagnosticBuffer.cpp
   TextDiagnostic.cpp
 
+  DISABLE_PCH_REUSE
+  PRECOMPILE_HEADERS
+  [["flang/Parser/parsing.h"]]
+  [["flang/Parser/parse-tree.h"]]
+  [["flang/Parser/dump-parse-tree.h"]]
+  [["flang/Lower/PFTBuilder.h"]]
+  [["flang/Lower/Bridge.h"]]
+
   DEPENDS
   CUFDialect
   FIRDialect
@@ -78,11 +86,3 @@ add_flang_library(flangFrontend
   clangBasic
   clangOptions
 )
-
-target_precompile_headers(flangFrontend PRIVATE
-  [["flang/Parser/parsing.h"]]
-  [["flang/Parser/parse-tree.h"]]
-  [["flang/Parser/dump-parse-tree.h"]]
-  [["flang/Lower/PFTBuilder.h"]]
-  [["flang/Lower/Bridge.h"]]
-)
diff --git a/flang/lib/Lower/CMakeLists.txt b/flang/lib/Lower/CMakeLists.txt
index 230a56ab66ec5..f5424c78b9a98 100644
--- a/flang/lib/Lower/CMakeLists.txt
+++ b/flang/lib/Lower/CMakeLists.txt
@@ -38,6 +38,17 @@ add_flang_library(FortranLower
   Support/Utils.cpp
   SymbolMap.cpp
   VectorSubscripts.cpp
+
+  DISABLE_PCH_REUSE
+  PRECOMPILE_HEADERS
+  [["flang/Lower/ConvertExpr.h"]]
+  [["flang/Lower/SymbolMap.h"]]
+  [["flang/Lower/AbstractConverter.h"]]
+  [["flang/Lower/IterationSpace.h"]]
+  [["flang/Lower/CallInterface.h"]]
+  [["flang/Lower/BoxAnalyzer.h"]]
+  [["flang/Lower/PFTBuilder.h"]]
+  [["flang/Lower/DirectivesCommon.h"]]
   
   DEPENDS
   CUFAttrs
@@ -79,14 +90,3 @@ add_flang_library(FortranLower
   MLIRLLVMDialect
   MLIRSCFToControlFlow
 )
-
-target_precompile_headers(FortranLower PRIVATE
-  [["flang/Lower/ConvertExpr.h"]]
-  [["flang/Lower/SymbolMap.h"]]
-  [["flang/Lower/AbstractConverter.h"]]
-  [["flang/Lower/IterationSpace.h"]]
-  [["flang/Lower/CallInterface.h"]]
-  [["flang/Lower/BoxAnalyzer.h"]]
-  [["flang/Lower/PFTBuilder.h"]]
-  [["flang/Lower/DirectivesCommon.h"]]
-)
diff --git a/flang/lib/Parser/CMakeLists.txt b/flang/lib/Parser/CMakeLists.txt
index 20c6c2a7c8f80..e0479b0da3eb8 100644
--- a/flang/lib/Parser/CMakeLists.txt
+++ b/flang/lib/Parser/CMakeLists.txt
@@ -25,6 +25,14 @@ add_flang_library(FortranParser
   unparse.cpp
   user-state.cpp
 
+  DISABLE_PCH_REUSE
+  PRECOMPILE_HEADERS
+  [["flang/Parser/parsing.h"]]
+  [["flang/Parser/parse-tree.h"]]
+  [["flang/Parser/provenance.h"]]
+  [["flang/Parser/message.h"]]
+  [["flang/Parser/parse-tree-visitor.h"]]
+
   LINK_LIBS
   FortranSupport
 
@@ -37,11 +45,3 @@ add_flang_library(FortranParser
   omp_gen
   acc_gen
 )
-
-target_precompile_headers(FortranParser PRIVATE
-  [["flang/Parser/parsing.h"]]
-  [["flang/Parser/parse-tree.h"]]
-  [["flang/Parser/provenance.h"]]
-  [["flang/Parser/message.h"]]
-  [["flang/Parser/parse-tree-visitor.h"]]
-)
diff --git a/flang/lib/Semantics/CMakeLists.txt 
b/flang/lib/Semantics/CMakeLists.txt
index 109bc2dbb8569..44e6dfb4dd09f 100644
--- a/flang/lib/Semantics/CMakeLists.txt
+++ b/flang/lib/Semantics/CMakeLists.txt
@@ -53,6 +53,15 @@ add_flang_library(FortranSemantics
   type.cpp
   unparse-with-symbols.cpp
 
+  DISABLE_PCH_REUSE
+  PRECOMPILE_HEADERS
+  [["flang/Semantics/semantics.h"]]
+  [["flang/Semantics/type.h"]]
+  [["flang/Semantics/openmp-modifiers.h"]]
+  [["flang/Semantics/expression.h"]]
+  [["flang/Semantics/tools.h"]]
+  [["flang/Semantics/symbol.h"]]
+
   DEPENDS
   acc_gen
   omp_gen
@@ -68,12 +77,3 @@ add_flang_library(FortranSemantics
   FrontendOpenACC
   TargetParser
 )
-
-target_precompile_headers(FortranSemantics PRIVATE
-  [["flang/Semantics/semantics.h"]]
-  [["flang/Semantics/type.h"]]
-  [["flang/Semantics/openmp-modifiers.h"]]
-  [["flang/Semantics/expression.h"]]
-  [["flang/Semantics/tools.h"]]
-  [["flang/Semantics/symbol.h"]]
-)
diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake
index d6acb4f984be9..71aeb8246669d 100644
--- a/llvm/cmake/modules/AddLLVM.cmake
+++ b/llvm/cmake/modules/AddLLVM.cmake
@@ -64,6 +64,57 @@ function(llvm_update_compile_flags name)
   target_compile_definitions(${name} PRIVATE ${LLVM_COMPILE_DEFINITIONS})
 endfunction()
 
+function(llvm_update_pch name)
+  if(LLVM_REQUIRES_RTTI OR LLVM_REQUIRES_EH)
+    # Non-default RTTI/EH results in incompatible flags, precluding PCH reuse.
+    return()
+  endif()
+
+  # Find PCH with highest priority from dependencies. We reuse the first PCH
+  # with the highest priority. If the target has its own set of PCH, we give it
+  # a higher priority so that dependents will prefer the new PCH. We don't do
+  # transitive PCH reuse, because this causes too many unrelated naming
+  # collisions (e.g., in A -> B -> C{pch}, only B would reuse the PCH of C).
+  set(pch_priority 0)
+  llvm_map_components_to_libnames(libs
+    ${LLVM_LINK_COMPONENTS}
+  )
+  list(APPEND libs ${ARG_LINK_LIBS})
+  foreach(lib ${libs})
+    if(TARGET ${lib})
+      get_target_property(lib_pch_priority ${lib} LLVM_PCH_PRIORITY)
+      #message(STATUS "PCH INFO: ${name} ${lib} ${lib_pch_priority}")
+      if(${lib_pch_priority} GREATER ${pch_priority})
+        set(pch_priority ${lib_pch_priority})
+        set(pch_reuse ${lib})
+      endif()
+    endif()
+  endforeach()
+
+  if(ARG_PRECOMPILE_HEADERS)
+    message(STATUS "Adding PCH ${ARG_PRECOMPILE_HEADERS} for ${name} (prio 
${pch_priority})")
+    target_precompile_headers(${name} PRIVATE 
$<$<COMPILE_LANGUAGE:CXX>:${ARG_PRECOMPILE_HEADERS}>)
+    if(NOT ARG_DISABLE_PCH_REUSE)
+      # Set priority so that dependants can reuse the PCH.
+      math(EXPR pch_priority "${pch_priority} + 1")
+      set_target_properties(${name} PROPERTIES LLVM_PCH_PRIORITY 
${pch_priority})
+    endif()
+  elseif(pch_reuse AND NOT ARG_DISABLE_PCH_REUSE)
+    # This loop is purely for debugging to see what the actually used PCH is.
+    while(FALSE)
+      get_target_property(pch_reuse_parent ${pch_reuse} 
PRECOMPILE_HEADERS_REUSE_FROM)
+      if(${pch_reuse_parent} STREQUAL "pch_reuse_parent-NOTFOUND")
+        break()
+      endif()
+      set(pch_reuse ${pch_reuse_parent})
+    endwhile()
+    message(STATUS "Using PCH ${pch_reuse} for ${name} (prio ${pch_priority})")
+    target_precompile_headers(${name} REUSE_FROM ${pch_reuse})
+  else()
+    message(STATUS "Using NO PCH for ${name}")
+  endif()
+endfunction()
+
 function(add_llvm_symbol_exports target_name export_file)
   if("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
     set(native_export_file "${target_name}.exports")
@@ -470,6 +521,13 @@ endfunction(set_windows_version_resource_properties)
 #     Corresponds to OUTPUT_NAME in target properties.
 #   DEPENDS targets...
 #     Same semantics as add_dependencies().
+#   PRECOMPILE_HEADERS include_directives...
+#     Pre-compiled C++ headers to use. PCH can be reused by dependants. If
+#     specified, no PCHs from dependencies will be reused.
+#   DISABLE_PCH_REUSE
+#     Disable reuse of pre-compiled headers in both directions: the library 
will
+#     not reuse the PCH of a dependency and a defined PCH will not be offered
+#     for reuse by dependants.
 #   LINK_COMPONENTS components...
 #     Same as the variable LLVM_LINK_COMPONENTS.
 #   LINK_LIBS lib_targets...
@@ -489,11 +547,12 @@ endfunction(set_windows_version_resource_properties)
 #   )
 function(llvm_add_library name)
   cmake_parse_arguments(ARG
-    
"MODULE;SHARED;STATIC;OBJECT;DISABLE_LLVM_LINK_LLVM_DYLIB;SONAME;NO_INSTALL_RPATH;COMPONENT_LIB"
+    
"MODULE;SHARED;STATIC;OBJECT;DISABLE_LLVM_LINK_LLVM_DYLIB;SONAME;NO_INSTALL_RPATH;COMPONENT_LIB;DISABLE_PCH_REUSE"
     "OUTPUT_NAME;PLUGIN_TOOL;ENTITLEMENTS;BUNDLE_PATH"
-    "ADDITIONAL_HEADERS;DEPENDS;LINK_COMPONENTS;LINK_LIBS;OBJLIBS"
+    
"ADDITIONAL_HEADERS;PRECOMPILE_HEADERS;DEPENDS;LINK_COMPONENTS;LINK_LIBS;OBJLIBS"
     ${ARGN})
   list(APPEND LLVM_COMMON_DEPENDS ${ARG_DEPENDS})
+  list(APPEND LLVM_LINK_COMPONENTS ${ARG_LINK_COMPONENTS})
   if(ARG_ADDITIONAL_HEADERS)
     # Pass through ADDITIONAL_HEADERS.
     set(ARG_ADDITIONAL_HEADERS ADDITIONAL_HEADERS ${ARG_ADDITIONAL_HEADERS})
@@ -535,6 +594,7 @@ function(llvm_add_library name)
       ${ALL_FILES}
       )
     llvm_update_compile_flags(${obj_name})
+    llvm_update_pch(${obj_name})
     if(CMAKE_GENERATOR STREQUAL "Xcode")
       set(DUMMY_FILE ${CMAKE_CURRENT_BINARY_DIR}/Dummy.c)
       file(WRITE ${DUMMY_FILE} "// This file intentionally empty\n")
@@ -589,7 +649,7 @@ function(llvm_add_library name)
       ${output_name}
       OBJLIBS ${ALL_FILES} # objlib
       LINK_LIBS ${ARG_LINK_LIBS}
-      LINK_COMPONENTS ${ARG_LINK_COMPONENTS}
+      LINK_COMPONENTS ${LLVM_LINK_COMPONENTS}
       )
     set_target_properties(${name_static} PROPERTIES FOLDER 
"${subproject_title}/Libraries")
 
@@ -661,6 +721,11 @@ function(llvm_add_library name)
   # $<TARGET_OBJECTS> doesn't require compile flags.
   if(NOT obj_name)
     llvm_update_compile_flags(${name})
+    llvm_update_pch(${name})
+  else()
+    target_precompile_headers(${name} REUSE_FROM ${obj_name})
+    get_target_property(pch_priority ${obj_name} LLVM_PCH_PRIORITY)
+    set_target_properties(${name} PROPERTIES LLVM_PCH_PRIORITY ${pch_priority})
   endif()
   add_link_opts( ${name} )
   if(ARG_OUTPUT_NAME)
@@ -743,8 +808,7 @@ function(llvm_add_library name)
         target_compile_definitions(${name} PRIVATE LLVM_BUILD_STATIC)
       endif()
       llvm_map_components_to_libnames(llvm_libs
-       ${ARG_LINK_COMPONENTS}
-       ${LLVM_LINK_COMPONENTS}
+        ${LLVM_LINK_COMPONENTS}
        )
     endif()
   else()
@@ -755,7 +819,7 @@ function(llvm_add_library name)
     # It would be nice to verify that we have the dependencies for this library
     # name, but using get_property(... SET) doesn't suffice to determine if a
     # property has been set to an empty value.
-    set_property(TARGET ${name} PROPERTY LLVM_LINK_COMPONENTS 
${ARG_LINK_COMPONENTS} ${LLVM_LINK_COMPONENTS})
+    set_property(TARGET ${name} PROPERTY LLVM_LINK_COMPONENTS 
${LLVM_LINK_COMPONENTS})
 
     # This property is an internal property only used to make sure the
     # link step applied in LLVMBuildResolveComponentsLink uses the same
@@ -978,6 +1042,7 @@ macro(generate_llvm_objects name)
       ${ALL_FILES}
       )
     llvm_update_compile_flags(${obj_name})
+    llvm_update_pch(${obj_name})
     set(ALL_FILES "$<TARGET_OBJECTS:${obj_name}>")
     if(ARG_DEPENDS)
       add_dependencies(${obj_name} ${ARG_DEPENDS})
@@ -1017,7 +1082,7 @@ endmacro()
 
 macro(add_llvm_executable name)
   cmake_parse_arguments(ARG
-    
"DISABLE_LLVM_LINK_LLVM_DYLIB;IGNORE_EXTERNALIZE_DEBUGINFO;NO_INSTALL_RPATH;SUPPORT_PLUGINS;EXPORT_SYMBOLS"
+    
"DISABLE_LLVM_LINK_LLVM_DYLIB;IGNORE_EXTERNALIZE_DEBUGINFO;NO_INSTALL_RPATH;SUPPORT_PLUGINS;EXPORT_SYMBOLS;DISABLE_PCH_REUSE"
     "ENTITLEMENTS;BUNDLE_PATH"
     ""
     ${ARGN})
@@ -1058,6 +1123,11 @@ macro(add_llvm_executable name)
   # $<TARGET_OBJECTS> doesn't require compile flags.
   if(NOT LLVM_ENABLE_OBJLIB)
     llvm_update_compile_flags(${name})
+    llvm_update_pch(${name})
+  else()
+    target_precompile_headers(${name} REUSE_FROM ${obj_name})
+    get_target_property(pch_priority ${obj_name} LLVM_PCH_PRIORITY)
+    set_target_properties(${name} PROPERTIES LLVM_PCH_PRIORITY ${pch_priority})
   endif()
 
   if (ARG_SUPPORT_PLUGINS AND NOT "${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
@@ -1765,7 +1835,7 @@ function(add_unittest test_suite test_name)
   endif()
 
   list(APPEND LLVM_LINK_COMPONENTS Support) # gtest needs it for raw_ostream
-  add_llvm_executable(${test_name} IGNORE_EXTERNALIZE_DEBUGINFO 
NO_INSTALL_RPATH ${ARGN})
+  add_llvm_executable(${test_name} IGNORE_EXTERNALIZE_DEBUGINFO 
NO_INSTALL_RPATH DISABLE_PCH_REUSE ${ARGN})
   get_subproject_title(subproject_title)
   set_target_properties(${test_name} PROPERTIES FOLDER 
"${subproject_title}/Tests/Unit")
 
diff --git a/llvm/cmake/modules/HandleLLVMOptions.cmake 
b/llvm/cmake/modules/HandleLLVMOptions.cmake
index 397aa0a6e0766..2e84fbe2b310f 100644
--- a/llvm/cmake/modules/HandleLLVMOptions.cmake
+++ b/llvm/cmake/modules/HandleLLVMOptions.cmake
@@ -1313,6 +1313,16 @@ if (LLVM_BUILD_INSTRUMENTED AND 
LLVM_BUILD_INSTRUMENTED_COVERAGE)
   message(FATAL_ERROR "LLVM_BUILD_INSTRUMENTED and 
LLVM_BUILD_INSTRUMENTED_COVERAGE cannot both be specified")
 endif()
 
+if(NOT CMAKE_DISABLE_PRECOMPILE_HEADERS)
+  if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+    # Clang requires this flag in order for precompiled headers to work with 
ccache
+    append("-Xclang -fno-pch-timestamp" CMAKE_CXX_FLAGS)
+  elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+    # GCC requires this flag in order for precompiled headers to work with 
ccache
+    append("-fpch-preprocess" CMAKE_CXX_FLAGS)
+  endif()
+endif()
+
 set(LLVM_THINLTO_CACHE_PATH "${PROJECT_BINARY_DIR}/lto.cache" CACHE STRING 
"Set ThinLTO cache path. This can be used when building LLVM from several 
different directiories.")
 
 if(LLVM_ENABLE_LTO AND WIN32 AND NOT LINKER_IS_LLD_LINK AND NOT MINGW)
diff --git 
a/llvm/examples/OrcV2Examples/OrcV2CBindingsAddObjectFile/CMakeLists.txt 
b/llvm/examples/OrcV2Examples/OrcV2CBindingsAddObjectFile/CMakeLists.txt
index cc50112f326ea..9a82cc0ed0916 100644
--- a/llvm/examples/OrcV2Examples/OrcV2CBindingsAddObjectFile/CMakeLists.txt
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsAddObjectFile/CMakeLists.txt
@@ -12,4 +12,6 @@ set(LLVM_LINK_COMPONENTS
 
 add_llvm_example(OrcV2CBindingsAddObjectFile
   OrcV2CBindingsAddObjectFile.c
+
+  DISABLE_PCH_REUSE # no C++ files, prevent CMake error.
   )
diff --git 
a/llvm/examples/OrcV2Examples/OrcV2CBindingsBasicUsage/CMakeLists.txt 
b/llvm/examples/OrcV2Examples/OrcV2CBindingsBasicUsage/CMakeLists.txt
index 0f18d6c24912f..1a738f60d15e1 100644
--- a/llvm/examples/OrcV2Examples/OrcV2CBindingsBasicUsage/CMakeLists.txt
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsBasicUsage/CMakeLists.txt
@@ -12,4 +12,6 @@ set(LLVM_LINK_COMPONENTS
 
 add_llvm_example(OrcV2CBindingsBasicUsage
   OrcV2CBindingsBasicUsage.c
+
+  DISABLE_PCH_REUSE # no C++ files, prevent CMake error.
   )
diff --git 
a/llvm/examples/OrcV2Examples/OrcV2CBindingsDumpObjects/CMakeLists.txt 
b/llvm/examples/OrcV2Examples/OrcV2CBindingsDumpObjects/CMakeLists.txt
index 8e2c97d782062..c7f748a12bf35 100644
--- a/llvm/examples/OrcV2Examples/OrcV2CBindingsDumpObjects/CMakeLists.txt
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsDumpObjects/CMakeLists.txt
@@ -12,4 +12,6 @@ set(LLVM_LINK_COMPONENTS
 
 add_llvm_example(OrcV2CBindingsDumpObjects
   OrcV2CBindingsDumpObjects.c
+
+  DISABLE_PCH_REUSE # no C++ files, prevent CMake error.
   )
diff --git 
a/llvm/examples/OrcV2Examples/OrcV2CBindingsIRTransforms/CMakeLists.txt 
b/llvm/examples/OrcV2Examples/OrcV2CBindingsIRTransforms/CMakeLists.txt
index af1b43e43e111..b152faf1e3527 100644
--- a/llvm/examples/OrcV2Examples/OrcV2CBindingsIRTransforms/CMakeLists.txt
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsIRTransforms/CMakeLists.txt
@@ -13,4 +13,6 @@ set(LLVM_LINK_COMPONENTS
 
 add_llvm_example(OrcV2CBindingsIRTransforms
   OrcV2CBindingsIRTransforms.c
+
+  DISABLE_PCH_REUSE # no C++ files, prevent CMake error.
   )
diff --git a/llvm/examples/OrcV2Examples/OrcV2CBindingsLazy/CMakeLists.txt 
b/llvm/examples/OrcV2Examples/OrcV2CBindingsLazy/CMakeLists.txt
index 52eb2d496fc23..c46700d9b2576 100644
--- a/llvm/examples/OrcV2Examples/OrcV2CBindingsLazy/CMakeLists.txt
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsLazy/CMakeLists.txt
@@ -12,4 +12,6 @@ set(LLVM_LINK_COMPONENTS
 
 add_llvm_example(OrcV2CBindingsLazy
   OrcV2CBindingsLazy.c
+
+  DISABLE_PCH_REUSE # no C++ files, prevent CMake error.
   )
diff --git 
a/llvm/examples/OrcV2Examples/OrcV2CBindingsMCJITLikeMemoryManager/CMakeLists.txt
 
b/llvm/examples/OrcV2Examples/OrcV2CBindingsMCJITLikeMemoryManager/CMakeLists.txt
index 4cdc2b114e9a5..d4a06104120c8 100644
--- 
a/llvm/examples/OrcV2Examples/OrcV2CBindingsMCJITLikeMemoryManager/CMakeLists.txt
+++ 
b/llvm/examples/OrcV2Examples/OrcV2CBindingsMCJITLikeMemoryManager/CMakeLists.txt
@@ -12,4 +12,6 @@ set(LLVM_LINK_COMPONENTS
 
 add_llvm_example(OrcV2CBindingsMCJITLikeMemoryManager
   OrcV2CBindingsMCJITLikeMemoryManager.c
+
+  DISABLE_PCH_REUSE # no C++ files, prevent CMake error.
   )
diff --git 
a/llvm/examples/OrcV2Examples/OrcV2CBindingsRemovableCode/CMakeLists.txt 
b/llvm/examples/OrcV2Examples/OrcV2CBindingsRemovableCode/CMakeLists.txt
index 5b737557bb1ef..441814054d9d1 100644
--- a/llvm/examples/OrcV2Examples/OrcV2CBindingsRemovableCode/CMakeLists.txt
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsRemovableCode/CMakeLists.txt
@@ -12,4 +12,6 @@ set(LLVM_LINK_COMPONENTS
 
 add_llvm_example(OrcV2CBindingsRemovableCode
   OrcV2CBindingsRemovableCode.c
+
+  DISABLE_PCH_REUSE # no C++ files, prevent CMake error.
   )
diff --git a/llvm/examples/OrcV2Examples/OrcV2CBindingsVeryLazy/CMakeLists.txt 
b/llvm/examples/OrcV2Examples/OrcV2CBindingsVeryLazy/CMakeLists.txt
index 0bc9610b1ad7e..6ec22f63875b9 100644
--- a/llvm/examples/OrcV2Examples/OrcV2CBindingsVeryLazy/CMakeLists.txt
+++ b/llvm/examples/OrcV2Examples/OrcV2CBindingsVeryLazy/CMakeLists.txt
@@ -12,4 +12,6 @@ set(LLVM_LINK_COMPONENTS
 
 add_llvm_example(OrcV2CBindingsVeryLazy
   OrcV2CBindingsVeryLazy.c
+
+  DISABLE_PCH_REUSE # no C++ files, prevent CMake error.
   )
diff --git a/llvm/include/llvm/Support/pch.h b/llvm/include/llvm/Support/pch.h
new file mode 100644
index 0000000000000..b1ff8698827ff
--- /dev/null
+++ b/llvm/include/llvm/Support/pch.h
@@ -0,0 +1,130 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// Precompiled header for LLVMSupport.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/ADL.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/VersionTuple.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <any>
+#include <array>
+#include <atomic>
+#include <bitset>
+#include <cassert>
+#include <cctype>
+#include <cerrno>
+#include <cfenv>
+#include <cfloat>
+#include <charconv>
+#include <chrono>
+#include <cinttypes>
+#include <climits>
+#include <cmath>
+#include <complex.h>
+#include <complex>
+#include <condition_variable>
+#include <csetjmp>
+#include <csignal>
+#include <cstdarg>
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#include <ctype.h>
+#include <cuchar>
+#include <cwchar>
+#include <cwctype>
+#include <deque>
+#include <errno.h>
+#include <exception>
+#include <execution>
+#include <fenv.h>
+#include <filesystem>
+#include <float.h>
+#include <forward_list>
+#include <fstream>
+#include <functional>
+#include <initializer_list>
+#include <iostream>
+#include <istream>
+#include <iterator>
+#include <limits>
+#include <list>
+#include <map>
+#include <math.h>
+#include <memory>
+#include <memory_resource>
+#include <mutex>
+#include <new>
+#include <numeric>
+#include <optional>
+#include <ostream>
+#include <queue>
+#include <random>
+#include <ratio>
+#include <regex>
+#include <scoped_allocator>
+#include <set>
+#include <shared_mutex>
+#include <sstream>
+#include <stack>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdexcept>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <streambuf>
+#include <string.h>
+#include <string>
+#include <string_view>
+#include <system_error>
+#include <tgmath.h>
+#include <thread>
+#include <tuple>
+#include <type_traits>
+#include <typeindex>
+#include <typeinfo>
+#include <uchar.h>
+#include <unordered_map>
+#include <unordered_set>
+#include <utility>
+#include <valarray>
+#include <variant>
+#include <vector>
+#include <wchar.h>
+#include <wctype.h>
diff --git a/llvm/lib/CMakeLists.txt b/llvm/lib/CMakeLists.txt
index 9af1854852436..f0faaff307997 100644
--- a/llvm/lib/CMakeLists.txt
+++ b/llvm/lib/CMakeLists.txt
@@ -3,8 +3,8 @@ include(LLVM-Build)
 # `Demangle', `Support' and `TableGen' libraries are added on the top-level
 # CMakeLists.txt
 
-add_subdirectory(ABI)
 add_subdirectory(IR)
+add_subdirectory(ABI)
 add_subdirectory(FuzzMutate)
 add_subdirectory(FileCheck)
 add_subdirectory(InterfaceStub)
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index 099b0e55579be..b4e39fced3853 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -135,7 +135,6 @@ if (UNIX AND "${CMAKE_SYSTEM_NAME}" MATCHES "AIX")
 endif()
 
 add_subdirectory(BLAKE3)
-add_subdirectory(LSP)
 
 add_llvm_component_library(LLVMSupport
   ABIBreak.cpp
@@ -322,6 +321,9 @@ add_llvm_component_library(LLVMSupport
   ${LLVM_MAIN_INCLUDE_DIR}/llvm/Support
   ${Backtrace_INCLUDE_DIRS}
 
+  PRECOMPILE_HEADERS
+  [["llvm/Support/pch.h"]]
+
   LINK_LIBS
   ${system_libs} ${imported_libs} ${delayload_flags}
 
@@ -396,3 +398,6 @@ target_include_directories(LLVMSupport
   PRIVATE
   ${LLVM_THIRD_PARTY_DIR}/siphash/include
 )
+
+# SupportLSP depends on Support and therefore must be included afterwards.
+add_subdirectory(LSP)
diff --git a/llvm/tools/llvm-c-test/CMakeLists.txt 
b/llvm/tools/llvm-c-test/CMakeLists.txt
index 939164e636216..8dd42b48e39a2 100644
--- a/llvm/tools/llvm-c-test/CMakeLists.txt
+++ b/llvm/tools/llvm-c-test/CMakeLists.txt
@@ -53,6 +53,8 @@ add_llvm_tool(llvm-c-test
   metadata.c
   object.c
   targets.c
+
+  DISABLE_PCH_REUSE # no C++ files, prevent CMake error.
   )
 
 if(USE_LLVM_DYLIB)
diff --git a/llvm/utils/count/CMakeLists.txt b/llvm/utils/count/CMakeLists.txt
index cfd1f4a85d8a1..4f53b72bf8203 100644
--- a/llvm/utils/count/CMakeLists.txt
+++ b/llvm/utils/count/CMakeLists.txt
@@ -4,4 +4,6 @@ set(LLVM_LINK_COMPONENTS
 
 add_llvm_utility(count
   count.c
+
+  DISABLE_PCH_REUSE # no C++ files, prevent CMake error.
   )
diff --git a/mlir/test/CAPI/CMakeLists.txt b/mlir/test/CAPI/CMakeLists.txt
index d45142510a496..3b4ee07b2283e 100644
--- a/mlir/test/CAPI/CMakeLists.txt
+++ b/mlir/test/CAPI/CMakeLists.txt
@@ -8,6 +8,7 @@ function(_add_capi_test_executable name)
     )
   add_llvm_executable(${name}
     PARTIAL_SOURCES_INTENDED
+    DISABLE_PCH_REUSE # no C++ files, prevent CMake error.
     ${ARG_UNPARSED_ARGUMENTS})
   set_target_properties(${name} PROPERTIES FOLDER "MLIR/Tests")
   set_target_properties(${name} PROPERTIES EXCLUDE_FROM_ALL ON)

>From 1b605e083e1fb2d12a7e63e4bce8c05665f89c39 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <[email protected]>
Date: Wed, 7 Jan 2026 13:08:45 +0000
Subject: [PATCH 04/12] [CMake][IR] Add PCH

---
 llvm/include/llvm/IR/pch.h | 31 +++++++++++++++++++++++++++++++
 llvm/lib/IR/CMakeLists.txt |  3 +++
 2 files changed, 34 insertions(+)
 create mode 100644 llvm/include/llvm/IR/pch.h

diff --git a/llvm/include/llvm/IR/pch.h b/llvm/include/llvm/IR/pch.h
new file mode 100644
index 0000000000000..b2fa937076d77
--- /dev/null
+++ b/llvm/include/llvm/IR/pch.h
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// Precompiled header for LLVMCore.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/CFG.h"
+#include "llvm/IR/Constant.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfoMetadata.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstVisitor.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/ModuleSummaryIndex.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/IR/PatternMatch.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Support/pch.h"
diff --git a/llvm/lib/IR/CMakeLists.txt b/llvm/lib/IR/CMakeLists.txt
index 31821a2d6b208..08bac979d4c90 100644
--- a/llvm/lib/IR/CMakeLists.txt
+++ b/llvm/lib/IR/CMakeLists.txt
@@ -83,6 +83,9 @@ add_llvm_component_library(LLVMCore
   ADDITIONAL_HEADER_DIRS
   ${LLVM_MAIN_INCLUDE_DIR}/llvm/IR
 
+  PRECOMPILE_HEADERS
+  [["llvm/IR/pch.h"]]
+
   LINK_LIBS
   ${LLVM_PTHREAD_LIB}
 

>From 3d3e54e7a7968d9d3617760a42d29318d0c89afa Mon Sep 17 00:00:00 2001
From: Alexis Engelke <[email protected]>
Date: Wed, 7 Jan 2026 13:09:09 +0000
Subject: [PATCH 05/12] [CMake][CodeGen] Add PCH

---
 llvm/include/llvm/CodeGen/pch.h | 25 +++++++++++++++++++++++++
 llvm/lib/CodeGen/CMakeLists.txt |  3 +++
 2 files changed, 28 insertions(+)
 create mode 100644 llvm/include/llvm/CodeGen/pch.h

diff --git a/llvm/include/llvm/CodeGen/pch.h b/llvm/include/llvm/CodeGen/pch.h
new file mode 100644
index 0000000000000..36eb560b3c003
--- /dev/null
+++ b/llvm/include/llvm/CodeGen/pch.h
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// Precompiled header for LLVMCodeGen.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/MachineScheduler.h"
+#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/CodeGen/SelectionDAGNodes.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/CodeGen/TargetLowering.h"
+#include "llvm/CodeGen/TargetRegisterInfo.h"
+#include "llvm/IR/pch.h"
+#include "llvm/Support/pch.h"
diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt
index f26b2cb6fddf5..21845da1da54b 100644
--- a/llvm/lib/CodeGen/CMakeLists.txt
+++ b/llvm/lib/CodeGen/CMakeLists.txt
@@ -267,6 +267,9 @@ add_llvm_component_library(LLVMCodeGen
   ${LLVM_MAIN_INCLUDE_DIR}/llvm/CodeGen
   ${LLVM_MAIN_INCLUDE_DIR}/llvm/CodeGen/PBQP
 
+  PRECOMPILE_HEADERS
+  [["llvm/CodeGen/pch.h"]]
+
   LINK_LIBS ${LLVM_PTHREAD_LIB} ${MLLinkDeps}
 
   DEPENDS

>From 06d5189659d5e09b5007dd98fb70e7154355c9d3 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <[email protected]>
Date: Wed, 7 Jan 2026 13:09:27 +0000
Subject: [PATCH 06/12] [CMake][AST] Add PCH

---
 clang/include/clang/AST/pch.h         | 32 +++++++++++++++++++++++++++
 clang/lib/AST/CMakeLists.txt          |  3 +++
 clang/lib/Frontend/TextDiagnostic.cpp |  4 ++--
 3 files changed, 37 insertions(+), 2 deletions(-)
 create mode 100644 clang/include/clang/AST/pch.h

diff --git a/clang/include/clang/AST/pch.h b/clang/include/clang/AST/pch.h
new file mode 100644
index 0000000000000..b048f866bc555
--- /dev/null
+++ b/clang/include/clang/AST/pch.h
@@ -0,0 +1,32 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// Precompiled header for clangAST.
+///
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/CanonicalType.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclOpenMP.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/GlobalDecl.h"
+#include "clang/AST/OpenMPClause.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtOpenMP.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "llvm/Support/pch.h"
diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt
index f9a5f4f0e7ecd..0e0a0c94d2ac5 100644
--- a/clang/lib/AST/CMakeLists.txt
+++ b/clang/lib/AST/CMakeLists.txt
@@ -136,6 +136,9 @@ add_clang_library(clangAST
   VTableBuilder.cpp
   VTTBuilder.cpp
 
+  PRECOMPILE_HEADERS
+  [["clang/AST/pch.h"]]
+
   LINK_LIBS
   clangBasic
   clangLex
diff --git a/clang/lib/Frontend/TextDiagnostic.cpp 
b/clang/lib/Frontend/TextDiagnostic.cpp
index 3f30709b0447e..196ab715206ff 100644
--- a/clang/lib/Frontend/TextDiagnostic.cpp
+++ b/clang/lib/Frontend/TextDiagnostic.cpp
@@ -37,7 +37,7 @@ static constexpr raw_ostream::Colors SavedColor = 
raw_ostream::SAVEDCOLOR;
 // is already taken for 'note'. Green is already used to underline
 // source ranges. White and black are bad because of the usual
 // terminal backgrounds. Which leaves us only with TWO options.
-static constexpr raw_ostream::Colors CommentColor = raw_ostream::YELLOW;
+static constexpr raw_ostream::Colors TCommentColor = raw_ostream::YELLOW;
 static constexpr raw_ostream::Colors LiteralColor = raw_ostream::GREEN;
 static constexpr raw_ostream::Colors KeywordColor = raw_ostream::BLUE;
 
@@ -1269,7 +1269,7 @@ highlightLines(StringRef FileData, unsigned 
StartLineNumber,
       Vec.emplace_back(Start, Start + Length, LiteralColor);
     } else {
       assert(T.is(tok::comment));
-      Vec.emplace_back(Start, Start + Length, CommentColor);
+      Vec.emplace_back(Start, Start + Length, TCommentColor);
     }
   };
 

>From 330e472e63981a2906a80f8a2cf832f8333493d3 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <[email protected]>
Date: Tue, 30 Dec 2025 11:10:43 +0000
Subject: [PATCH 07/12] pch for unittests

---
 clang/unittests/Basic/CharInfoTest.cpp            |  1 -
 .../Interpreter/ExceptionTests/CMakeLists.txt     |  2 +-
 llvm/cmake/modules/AddLLVM.cmake                  | 12 ++++++++++--
 llvm/unittests/Support/raw_sha1_ostream_test.cpp  | 15 +--------------
 third-party/unittest/CMakeLists.txt               |  7 ++++++-
 5 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/clang/unittests/Basic/CharInfoTest.cpp 
b/clang/unittests/Basic/CharInfoTest.cpp
index 491c9afceb6f8..09b827be35397 100644
--- a/clang/unittests/Basic/CharInfoTest.cpp
+++ b/clang/unittests/Basic/CharInfoTest.cpp
@@ -9,7 +9,6 @@
 #include "clang/Basic/CharInfo.h"
 #include "gtest/gtest.h"
 
-using namespace llvm;
 using namespace clang;
 
 // Check that the CharInfo table has been constructed reasonably.
diff --git a/clang/unittests/Interpreter/ExceptionTests/CMakeLists.txt 
b/clang/unittests/Interpreter/ExceptionTests/CMakeLists.txt
index dfd94d8e6442c..5ea752b77f6f9 100644
--- a/clang/unittests/Interpreter/ExceptionTests/CMakeLists.txt
+++ b/clang/unittests/Interpreter/ExceptionTests/CMakeLists.txt
@@ -1,7 +1,7 @@
 # The interpreter can throw an exception from user input. The test binary needs
 # to be compiled with exception support to catch the thrown exception.
 set(LLVM_REQUIRES_EH ON)
-set(LLVM_REQUIRES_RTTI ON)
+set(LLVM_REQUIRES_RTTI OFF)
 
 add_distinct_clang_unittest(ClangReplInterpreterExceptionTests
   InterpreterExceptionTest.cpp
diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake
index 71aeb8246669d..e27db837dc287 100644
--- a/llvm/cmake/modules/AddLLVM.cmake
+++ b/llvm/cmake/modules/AddLLVM.cmake
@@ -26,8 +26,9 @@ function(llvm_update_compile_flags name)
   # force EH
   if(LLVM_REQUIRES_EH OR LLVM_ENABLE_EH)
     if(NOT (LLVM_REQUIRES_RTTI OR LLVM_ENABLE_RTTI))
-      message(AUTHOR_WARNING "Exception handling requires RTTI. Enabling RTTI 
for ${name}")
-      set(LLVM_REQUIRES_RTTI ON)
+      # XXX: still required?
+      #message(AUTHOR_WARNING "Exception handling requires RTTI. Enabling RTTI 
for ${name}")
+      #set(LLVM_REQUIRES_RTTI ON)
     endif()
     if(MSVC)
       list(APPEND LLVM_COMPILE_CXXFLAGS "/EHsc")
@@ -1850,8 +1851,15 @@ function(add_unittest test_suite test_name)
   # If it is not defined, fall back to llvm_gtest.
   if(TARGET default_gtest)
     target_link_libraries(${test_name} PRIVATE default_gtest_main 
default_gtest ${LLVM_PTHREAD_LIB})
+    # Runtime builds are too diverse in compiler flags/defines.
+    if(NOT LLVM_RUNTIMES_BUILD AND NOT LLVM_REQUIRES_RTTI AND NOT 
LLVM_REQUIRES_EH)
+      target_precompile_headers(${test_name} REUSE_FROM default_gtest)
+    endif()
   else ()
     target_link_libraries(${test_name} PRIVATE llvm_gtest_main llvm_gtest 
${LLVM_PTHREAD_LIB})
+    if(NOT LLVM_REQUIRES_RTTI AND NOT LLVM_REQUIRES_EH)
+      target_precompile_headers(${test_name} REUSE_FROM llvm_gtest)
+    endif()
   endif ()
 
   add_dependencies(${test_suite} ${test_name})
diff --git a/llvm/unittests/Support/raw_sha1_ostream_test.cpp 
b/llvm/unittests/Support/raw_sha1_ostream_test.cpp
index a3cb6f58d3e29..be8333237d81d 100644
--- a/llvm/unittests/Support/raw_sha1_ostream_test.cpp
+++ b/llvm/unittests/Support/raw_sha1_ostream_test.cpp
@@ -6,6 +6,7 @@
 //
 
//===----------------------------------------------------------------------===//
 
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/raw_sha1_ostream.h"
 #include "gtest/gtest.h"
@@ -14,20 +15,6 @@
 
 using namespace llvm;
 
-static std::string toHex(ArrayRef<uint8_t> Input) {
-  static const char *const LUT = "0123456789ABCDEF";
-  size_t Length = Input.size();
-
-  std::string Output;
-  Output.reserve(2 * Length);
-  for (size_t i = 0; i < Length; ++i) {
-    const unsigned char c = Input[i];
-    Output.push_back(LUT[c >> 4]);
-    Output.push_back(LUT[c & 15]);
-  }
-  return Output;
-}
-
 TEST(raw_sha1_ostreamTest, Basic) {
   llvm::raw_sha1_ostream Sha1Stream;
   Sha1Stream << "Hello World!";
diff --git a/third-party/unittest/CMakeLists.txt 
b/third-party/unittest/CMakeLists.txt
index 79535a1de4616..29dd670ba33f7 100644
--- a/third-party/unittest/CMakeLists.txt
+++ b/third-party/unittest/CMakeLists.txt
@@ -13,6 +13,8 @@
 
 set(LLVM_SUBPROJECT_TITLE "Third-Party/Google Test")
 
+set(GTEST_PCH [["gtest/gtest.h"]])
+
 if(LLVM_RUNTIMES_BUILD)
   # This instance of GTest is use for unittests for the runtime libraries. It
   # must not link to LLVMSupport (used for llvm::raw_ostream and llvm::cl
@@ -37,6 +39,7 @@ else()
   set(GTEST_LLVM_COMPONENTS "Support")
   set(gtest_name "llvm_gtest")
   set(gtest_main_src UnitTestMain/TestMain.cpp)
+  list(APPEND GTEST_PCH [["llvm/Support/pch.h"]])
 endif()
 
 if(WIN32)
@@ -59,7 +62,6 @@ if(CXX_SUPPORTS_COVERED_SWITCH_DEFAULT_FLAG)
   add_definitions("-Wno-covered-switch-default")
 endif()
 
-set(LLVM_REQUIRES_RTTI 1)
 add_definitions( -DGTEST_HAS_RTTI=0 )
 
 if (HAVE_LIBPTHREAD)
@@ -76,6 +78,9 @@ add_llvm_library("${gtest_name}"
   googletest/src/gtest-all.cc
   googlemock/src/gmock-all.cc
 
+  PRECOMPILE_HEADERS
+  ${GTEST_PCH}
+
   LINK_LIBS
   ${LIBS}
 

>From f83f964d3a6f64802f31f5bbc24a969bcd54fb10 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <[email protected]>
Date: Wed, 7 Jan 2026 14:19:03 +0000
Subject: [PATCH 08/12] [Support][NFC] Move JSON::dump out-of-line to prevent
 redundant compilation

---
 llvm/include/llvm/Support/JSON.h | 5 +----
 llvm/lib/Support/JSON.cpp        | 7 +++++++
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/llvm/include/llvm/Support/JSON.h b/llvm/include/llvm/Support/JSON.h
index a58332c912942..72e5a65dfea12 100644
--- a/llvm/include/llvm/Support/JSON.h
+++ b/llvm/include/llvm/Support/JSON.h
@@ -477,10 +477,7 @@ class Value {
 
   LLVM_ABI void print(llvm::raw_ostream &OS) const;
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-  LLVM_DUMP_METHOD void dump() const {
-    print(llvm::dbgs());
-    llvm::dbgs() << '\n';
-  }
+  LLVM_DUMP_METHOD void dump() const;
 #endif // !NDEBUG || LLVM_ENABLE_DUMP
 
 private:
diff --git a/llvm/lib/Support/JSON.cpp b/llvm/lib/Support/JSON.cpp
index 4652c0740dc4d..e9fd8f8fae1fa 100644
--- a/llvm/lib/Support/JSON.cpp
+++ b/llvm/lib/Support/JSON.cpp
@@ -175,6 +175,13 @@ void Value::destroy() {
 
 void Value::print(llvm::raw_ostream &OS) const { OS << *this; }
 
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_DUMP_METHOD void Value::dump() const {
+  print(llvm::dbgs());
+  llvm::dbgs() << '\n';
+}
+#endif
+
 bool operator==(const Value &L, const Value &R) {
   if (L.kind() != R.kind())
     return false;

>From 45db8db4384d6312dd24833c9d726889d9dc7478 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <[email protected]>
Date: Wed, 7 Jan 2026 14:35:32 +0000
Subject: [PATCH 09/12] fixup! [CMake][LLVM] Add PCH infrastructure and
 LLVMSupport PCH

---
 llvm/cmake/modules/AddLLVM.cmake | 9 ++++-----
 llvm/include/llvm/Support/pch.h  | 3 ++-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake
index e27db837dc287..89d0191b27878 100644
--- a/llvm/cmake/modules/AddLLVM.cmake
+++ b/llvm/cmake/modules/AddLLVM.cmake
@@ -68,7 +68,7 @@ endfunction()
 function(llvm_update_pch name)
   if(LLVM_REQUIRES_RTTI OR LLVM_REQUIRES_EH)
     # Non-default RTTI/EH results in incompatible flags, precluding PCH reuse.
-    return()
+    set(ARG_DISABLE_PCH_REUSE ON)
   endif()
 
   # Find PCH with highest priority from dependencies. We reuse the first PCH
@@ -84,7 +84,6 @@ function(llvm_update_pch name)
   foreach(lib ${libs})
     if(TARGET ${lib})
       get_target_property(lib_pch_priority ${lib} LLVM_PCH_PRIORITY)
-      #message(STATUS "PCH INFO: ${name} ${lib} ${lib_pch_priority}")
       if(${lib_pch_priority} GREATER ${pch_priority})
         set(pch_priority ${lib_pch_priority})
         set(pch_reuse ${lib})
@@ -93,7 +92,7 @@ function(llvm_update_pch name)
   endforeach()
 
   if(ARG_PRECOMPILE_HEADERS)
-    message(STATUS "Adding PCH ${ARG_PRECOMPILE_HEADERS} for ${name} (prio 
${pch_priority})")
+    message(DEBUG "Adding PCH ${ARG_PRECOMPILE_HEADERS} for ${name} (prio 
${pch_priority})")
     target_precompile_headers(${name} PRIVATE 
$<$<COMPILE_LANGUAGE:CXX>:${ARG_PRECOMPILE_HEADERS}>)
     if(NOT ARG_DISABLE_PCH_REUSE)
       # Set priority so that dependants can reuse the PCH.
@@ -109,10 +108,10 @@ function(llvm_update_pch name)
       endif()
       set(pch_reuse ${pch_reuse_parent})
     endwhile()
-    message(STATUS "Using PCH ${pch_reuse} for ${name} (prio ${pch_priority})")
+    message(DEBUG "Using PCH ${pch_reuse} for ${name} (prio ${pch_priority})")
     target_precompile_headers(${name} REUSE_FROM ${pch_reuse})
   else()
-    message(STATUS "Using NO PCH for ${name}")
+    message(DEBUG "Using NO PCH for ${name}")
   endif()
 endfunction()
 
diff --git a/llvm/include/llvm/Support/pch.h b/llvm/include/llvm/Support/pch.h
index b1ff8698827ff..9265f366df587 100644
--- a/llvm/include/llvm/Support/pch.h
+++ b/llvm/include/llvm/Support/pch.h
@@ -79,7 +79,8 @@
 #include <fstream>
 #include <functional>
 #include <initializer_list>
-#include <iostream>
+// iostream is banned.
+// #include <iostream>
 #include <istream>
 #include <iterator>
 #include <limits>

>From 92ca4a5d14610b697456d44981a535f40a50f931 Mon Sep 17 00:00:00 2001
From: Alexis Engelke <[email protected]>
Date: Wed, 7 Jan 2026 17:32:31 +0000
Subject: [PATCH 10/12] [CMake][CodeGen] Add PCH for Clang CodeGen

---
 clang/lib/CodeGen/CGLoopInfo.cpp |  5 ++++-
 clang/lib/CodeGen/CMakeLists.txt |  4 ++++
 clang/lib/CodeGen/pch.h          | 22 ++++++++++++++++++++++
 3 files changed, 30 insertions(+), 1 deletion(-)
 create mode 100644 clang/lib/CodeGen/pch.h

diff --git a/clang/lib/CodeGen/CGLoopInfo.cpp b/clang/lib/CodeGen/CGLoopInfo.cpp
index b2b569a43038c..4a580fc58f940 100644
--- a/clang/lib/CodeGen/CGLoopInfo.cpp
+++ b/clang/lib/CodeGen/CGLoopInfo.cpp
@@ -18,9 +18,11 @@
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Metadata.h"
 #include <optional>
-using namespace clang::CodeGen;
 using namespace llvm;
 
+// No using namespace to avoid collision with llvm::LoopInfo.
+namespace clang::CodeGen {
+
 MDNode *
 LoopInfo::createFollowupMetadata(const char *FollowupName,
                                  ArrayRef<llvm::Metadata *> LoopProperties) {
@@ -863,3 +865,4 @@ void LoopInfoStack::InsertHelper(Instruction *I) const {
     return;
   }
 }
+} // end namespace clang::CodeGen
diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt
index dbbc35b372f42..cf08938c349b2 100644
--- a/clang/lib/CodeGen/CMakeLists.txt
+++ b/clang/lib/CodeGen/CMakeLists.txt
@@ -158,6 +158,10 @@ add_clang_library(clangCodeGen
   TrapReasonBuilder.cpp
   VarBypassDetector.cpp
 
+  DISABLE_PCH_REUSE # PCH contains private headers
+  PRECOMPILE_HEADERS
+  [["pch.h"]]
+
   DEPENDS
   vt_gen
   intrinsics_gen
diff --git a/clang/lib/CodeGen/pch.h b/clang/lib/CodeGen/pch.h
new file mode 100644
index 0000000000000..137fe034dd83b
--- /dev/null
+++ b/clang/lib/CodeGen/pch.h
@@ -0,0 +1,22 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// Precompiled header for clangCodeGen. Uses private headers.
+///
+//===----------------------------------------------------------------------===//
+
+#include "ABIInfoImpl.h"
+#include "Address.h"
+#include "CGBuilder.h"
+#include "CGCXXABI.h"
+#include "CGValue.h"
+#include "CodeGenFunction.h"
+#include "CodeGenModule.h"
+#include "clang/AST/pch.h"
+#include "llvm/IR/pch.h"
+#include "llvm/Support/pch.h"

>From 5be1e67e1dff3764ded8d46ff54a50e6560c5c4f Mon Sep 17 00:00:00 2001
From: Alexis Engelke <[email protected]>
Date: Wed, 7 Jan 2026 17:32:59 +0000
Subject: [PATCH 11/12] [Transforms][NFC] Remove unused include in LoopUtils

This avoid pulling in LoopAccessAnalysis in ~45 source files.
---
 llvm/include/llvm/Transforms/Utils/LoopUtils.h    | 3 +--
 llvm/lib/Transforms/Scalar/LoopFlatten.cpp        | 1 +
 llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp | 1 +
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Utils/LoopUtils.h 
b/llvm/include/llvm/Transforms/Utils/LoopUtils.h
index 42ed3c659edd9..0f7ee82a6ff64 100644
--- a/llvm/include/llvm/Transforms/Utils/LoopUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/LoopUtils.h
@@ -13,8 +13,6 @@
 #ifndef LLVM_TRANSFORMS_UTILS_LOOPUTILS_H
 #define LLVM_TRANSFORMS_UTILS_LOOPUTILS_H
 
-#include "llvm/Analysis/IVDescriptors.h"
-#include "llvm/Analysis/LoopAccessAnalysis.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Transforms/Utils/ValueMapper.h"
@@ -37,6 +35,7 @@ class MemoryAccess;
 class MemorySSA;
 class MemorySSAUpdater;
 class OptimizationRemarkEmitter;
+struct PointerDiffInfo;
 class PredIteratorCache;
 class ScalarEvolution;
 class SCEV;
diff --git a/llvm/lib/Transforms/Scalar/LoopFlatten.cpp 
b/llvm/lib/Transforms/Scalar/LoopFlatten.cpp
index d8b611076efea..2796482f97b73 100644
--- a/llvm/lib/Transforms/Scalar/LoopFlatten.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopFlatten.cpp
@@ -53,6 +53,7 @@
 
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/AssumptionCache.h"
+#include "llvm/Analysis/LoopAccessAnalysis.h"
 #include "llvm/Analysis/LoopInfo.h"
 #include "llvm/Analysis/LoopNestAnalysis.h"
 #include "llvm/Analysis/MemorySSAUpdater.h"
diff --git a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp 
b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
index cdbd0af4cbeaf..b618aa198632c 100644
--- a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
@@ -40,6 +40,7 @@
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/Analysis/CmpInstAnalysis.h"
 #include "llvm/Analysis/HashRecognize.h"
+#include "llvm/Analysis/LoopAccessAnalysis.h"
 #include "llvm/Analysis/LoopInfo.h"
 #include "llvm/Analysis/LoopPass.h"
 #include "llvm/Analysis/MemoryLocation.h"

>From 0b4660f3eef766995d5012d01abf4fa61fab4efd Mon Sep 17 00:00:00 2001
From: Alexis Engelke <[email protected]>
Date: Thu, 8 Jan 2026 20:01:29 +0000
Subject: [PATCH 12/12] fixup! fixup! [CMake][LLVM] Add PCH infrastructure and
 LLVMSupport PCH

Reduce number of Support PCH headers for GCC.
---
 llvm/include/llvm/Support/pch.h | 56 ---------------------------------
 1 file changed, 56 deletions(-)

diff --git a/llvm/include/llvm/Support/pch.h b/llvm/include/llvm/Support/pch.h
index 9265f366df587..ccfeceb231f61 100644
--- a/llvm/include/llvm/Support/pch.h
+++ b/llvm/include/llvm/Support/pch.h
@@ -32,100 +32,44 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/JSON.h"
-#include "llvm/Support/ScopedPrinter.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/VersionTuple.h"
 #include "llvm/Support/YAMLTraits.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
-#include <any>
 #include <array>
 #include <atomic>
 #include <bitset>
 #include <cassert>
-#include <cctype>
-#include <cerrno>
-#include <cfenv>
-#include <cfloat>
-#include <charconv>
 #include <chrono>
-#include <cinttypes>
 #include <climits>
 #include <cmath>
-#include <complex.h>
-#include <complex>
-#include <condition_variable>
-#include <csetjmp>
-#include <csignal>
-#include <cstdarg>
 #include <cstddef>
 #include <cstdint>
-#include <cstdio>
 #include <cstdlib>
 #include <cstring>
 #include <ctime>
-#include <ctype.h>
-#include <cuchar>
-#include <cwchar>
-#include <cwctype>
 #include <deque>
-#include <errno.h>
-#include <exception>
-#include <execution>
-#include <fenv.h>
-#include <filesystem>
-#include <float.h>
-#include <forward_list>
-#include <fstream>
 #include <functional>
 #include <initializer_list>
-// iostream is banned.
-// #include <iostream>
-#include <istream>
 #include <iterator>
 #include <limits>
 #include <list>
 #include <map>
-#include <math.h>
 #include <memory>
-#include <memory_resource>
 #include <mutex>
 #include <new>
-#include <numeric>
 #include <optional>
-#include <ostream>
 #include <queue>
-#include <random>
-#include <ratio>
-#include <regex>
-#include <scoped_allocator>
 #include <set>
-#include <shared_mutex>
 #include <sstream>
-#include <stack>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdexcept>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <streambuf>
-#include <string.h>
 #include <string>
 #include <string_view>
 #include <system_error>
-#include <tgmath.h>
-#include <thread>
 #include <tuple>
 #include <type_traits>
-#include <typeindex>
-#include <typeinfo>
-#include <uchar.h>
 #include <unordered_map>
 #include <unordered_set>
 #include <utility>
-#include <valarray>
 #include <variant>
 #include <vector>
-#include <wchar.h>
-#include <wctype.h>

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to