[clang] [llvm] Compute GUIDs once and store in metadata (PR #184065)

Owen Rodley via cfe-commits cfe-commits at lists.llvm.org
Sun Mar 29 21:25:27 PDT 2026


https://github.com/orodley updated https://github.com/llvm/llvm-project/pull/184065

>From 545736555c3b8ff78b5f87f761ba2df783882bdf Mon Sep 17 00:00:00 2001
From: Owen Rodley <orodley at google.com>
Date: Tue, 2 Sep 2025 13:52:05 +1000
Subject: [PATCH 1/7] Compute GUIDs once and store in metadata

This allows us to keep GUIDs consistent across compilation phases which may
change the name or linkage type.

See https://discourse.llvm.org/t/rfc-keep-globalvalue-guids-stable/84801
---
 llvm/include/llvm/Analysis/CtxProfAnalysis.h  | 36 ++--------
 llvm/include/llvm/Bitcode/BitcodeReader.h     |  4 +-
 llvm/include/llvm/Bitcode/LLVMBitCodes.h      |  3 +
 llvm/include/llvm/IR/FixedMetadataKinds.def   |  1 +
 llvm/include/llvm/IR/GlobalValue.h            | 33 ++++++++--
 llvm/include/llvm/IR/Module.h                 | 16 +++++
 llvm/include/llvm/IR/ModuleSummaryIndex.h     | 16 +++--
 llvm/include/llvm/LTO/LTO.h                   | 17 +++++
 .../llvm/Transforms/Utils/AssignGUID.h        | 42 ++++++++++++
 llvm/lib/Analysis/CtxProfAnalysis.cpp         | 44 ++-----------
 llvm/lib/AsmParser/LLParser.cpp               | 12 +++-
 llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp   |  1 +
 llvm/lib/Bitcode/Reader/BitcodeReader.cpp     | 66 ++++++++++++++-----
 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp     | 47 ++++++++++++-
 llvm/lib/IR/Globals.cpp                       | 42 ++++++++++++
 llvm/lib/LTO/LTO.cpp                          | 51 ++++++++------
 llvm/lib/LTO/LTOBackend.cpp                   |  9 ++-
 llvm/lib/Passes/PassBuilder.cpp               |  1 +
 llvm/lib/Passes/PassBuilderPipelines.cpp      |  9 ++-
 llvm/lib/Transforms/IPO/FunctionImport.cpp    | 60 +++++++++++------
 .../Transforms/IPO/ThinLTOBitcodeWriter.cpp   |  2 +
 .../lib/Transforms/IPO/WholeProgramDevirt.cpp |  7 ++
 .../Instrumentation/PGOCtxProfFlattening.cpp  |  4 +-
 .../Instrumentation/PGOCtxProfLowering.cpp    |  3 +-
 .../Transforms/Scalar/JumpTableToSwitch.cpp   |  5 +-
 llvm/lib/Transforms/Utils/AssignGUID.cpp      | 31 +++++++++
 llvm/lib/Transforms/Utils/CMakeLists.txt      |  1 +
 .../Transforms/Utils/CallPromotionUtils.cpp   |  5 +-
 llvm/lib/Transforms/Utils/CloneModule.cpp     |  6 +-
 .../Transforms/Utils/FunctionImportUtils.cpp  | 19 +++++-
 llvm/lib/Transforms/Utils/InlineFunction.cpp  |  4 +-
 llvm/test/Assembler/index-value-order.ll      |  9 ++-
 llvm/test/Bitcode/thinlto-alias.ll            |  1 +
 ...allgraph-partial-sample-profile-summary.ll |  5 +-
 .../thinlto-function-summary-callgraph-pgo.ll |  1 +
 ...ction-summary-callgraph-profile-summary.ll |  5 +-
 ...ummary-callgraph-sample-profile-summary.ll |  5 +-
 .../thinlto-function-summary-callgraph.ll     |  1 +
 .../thinlto-function-summary-refgraph.ll      |  1 +
 llvm/test/Bitcode/thinlto-function-summary.ll |  1 +
 llvm/test/CodeGen/X86/fat-lto-section.ll      |  2 +-
 llvm/test/Linker/funcimport2.ll               |  2 +-
 llvm/test/Other/new-pm-O0-defaults.ll         |  3 +-
 llvm/test/Other/new-pm-defaults.ll            |  3 +-
 .../Other/new-pm-thinlto-prelink-defaults.ll  |  3 +-
 .../new-pm-thinlto-prelink-pgo-defaults.ll    |  3 +-
 ...w-pm-thinlto-prelink-samplepgo-defaults.ll |  1 +
 llvm/test/ThinLTO/AArch64/aarch64_inline.ll   |  2 +-
 llvm/test/ThinLTO/X86/ctor-dtor-alias.ll      |  4 +-
 llvm/test/ThinLTO/X86/ctor-dtor-alias2.ll     |  4 +-
 llvm/test/ThinLTO/X86/deadstrip.ll            |  8 +--
 llvm/test/ThinLTO/X86/distributed_import.ll   |  4 +-
 .../X86/funcattrs-prop-exported-internal.ll   |  4 +-
 .../ThinLTO/X86/funcattrs-prop-unknown.ll     |  6 +-
 llvm/test/ThinLTO/X86/globals-import.ll       |  4 +-
 .../ThinLTO/X86/hidden-escaped-symbols-alt.ll |  2 +-
 .../ThinLTO/X86/hidden-escaped-symbols.ll     |  2 +-
 llvm/test/ThinLTO/X86/import-ro-constant.ll   |  2 +-
 .../ThinLTO/X86/index-const-prop-alias.ll     |  2 +-
 llvm/test/ThinLTO/X86/index-const-prop.ll     |  6 +-
 .../ThinLTO/X86/linkonce_resolution_comdat.ll | 16 ++---
 llvm/test/ThinLTO/X86/memprof-dups.ll         |  2 +-
 .../X86/memprof_callee_type_mismatch.ll       |  2 +-
 .../ThinLTO/X86/memprof_imported_internal.ll  |  2 +-
 .../ThinLTO/X86/memprof_imported_internal2.ll |  2 +-
 .../X86/prevailing_weak_globals_import.ll     |  2 +-
 llvm/test/ThinLTO/X86/visibility-elf.ll       |  6 +-
 llvm/test/ThinLTO/X86/visibility-macho.ll     |  4 +-
 llvm/test/ThinLTO/X86/windows-vftable.ll      |  4 +-
 llvm/test/ThinLTO/X86/writeonly.ll            |  4 +-
 .../test/Transforms/AssignGUID/assign_guid.ll | 18 +++++
 .../test/Transforms/EmbedBitcode/embed-wpd.ll |  2 +-
 llvm/test/Transforms/EmbedBitcode/embed.ll    | 13 ++--
 .../funcimport-debug-retained-nodes.ll        |  3 +-
 .../Transforms/FunctionImport/funcimport.ll   | 24 +++----
 .../LowerTypeTests/cfi-icall-alias.ll         |  2 +-
 .../thinlto_indirect_call_promotion.ll        |  4 +-
 .../speculative-devirt-then-inliner.ll        |  2 +-
 .../test/Transforms/SampleProfile/ctxsplit.ll |  8 +--
 .../ThinLTOBitcodeWriter/split-internal2.ll   |  6 +-
 .../ThinLTOBitcodeWriter/split-vfunc.ll       | 14 ++--
 .../ThinLTOBitcodeWriter/unsplittable.ll      |  2 +-
 .../branch-funnel-profile.ll                  | 44 ++++++-------
 .../WholeProgramDevirt/export-single-impl.ll  |  4 +-
 .../WholeProgramDevirt/export-vcp.ll          |  6 +-
 llvm/tools/llvm-link/llvm-link.cpp            |  4 +-
 llvm/tools/opt/NewPMDriver.cpp                |  8 +++
 87 files changed, 605 insertions(+), 296 deletions(-)
 create mode 100644 llvm/include/llvm/Transforms/Utils/AssignGUID.h
 create mode 100644 llvm/lib/Transforms/Utils/AssignGUID.cpp
 create mode 100644 llvm/test/Transforms/AssignGUID/assign_guid.ll

diff --git a/llvm/include/llvm/Analysis/CtxProfAnalysis.h b/llvm/include/llvm/Analysis/CtxProfAnalysis.h
index 5c9823b0f6cc1..90b1d3fc0a688 100644
--- a/llvm/include/llvm/Analysis/CtxProfAnalysis.h
+++ b/llvm/include/llvm/Analysis/CtxProfAnalysis.h
@@ -47,9 +47,6 @@ class PGOContextualProfile {
   // we'll need when we maintain the profiles during IPO transformations.
   std::map<GlobalValue::GUID, FunctionInfo> FuncInfo;
 
-  /// Get the GUID of this Function if it's defined in this module.
-  LLVM_ABI GlobalValue::GUID getDefinedFunctionGUID(const Function &F) const;
-
   // This is meant to be constructed from CtxProfAnalysis, which will also set
   // its state piecemeal.
   PGOContextualProfile() = default;
@@ -68,9 +65,7 @@ class PGOContextualProfile {
 
   LLVM_ABI bool isInSpecializedModule() const;
 
-  bool isFunctionKnown(const Function &F) const {
-    return getDefinedFunctionGUID(F) != 0;
-  }
+  bool isFunctionKnown(const Function &F) const { return !F.isDeclaration(); }
 
   StringRef getFunctionName(GlobalValue::GUID GUID) const {
     auto It = FuncInfo.find(GUID);
@@ -81,22 +76,22 @@ class PGOContextualProfile {
 
   uint32_t getNumCounters(const Function &F) const {
     assert(isFunctionKnown(F));
-    return FuncInfo.find(getDefinedFunctionGUID(F))->second.NextCounterIndex;
+    return FuncInfo.find(F.getGUID())->second.NextCounterIndex;
   }
 
   uint32_t getNumCallsites(const Function &F) const {
     assert(isFunctionKnown(F));
-    return FuncInfo.find(getDefinedFunctionGUID(F))->second.NextCallsiteIndex;
+    return FuncInfo.find(F.getGUID())->second.NextCallsiteIndex;
   }
 
   uint32_t allocateNextCounterIndex(const Function &F) {
     assert(isFunctionKnown(F));
-    return FuncInfo.find(getDefinedFunctionGUID(F))->second.NextCounterIndex++;
+    return FuncInfo.find(F.getGUID())->second.NextCounterIndex++;
   }
 
   uint32_t allocateNextCallsiteIndex(const Function &F) {
     assert(isFunctionKnown(F));
-    return FuncInfo.find(getDefinedFunctionGUID(F))->second.NextCallsiteIndex++;
+    return FuncInfo.find(F.getGUID())->second.NextCallsiteIndex++;
   }
 
   using ConstVisitor = function_ref<void(const PGOCtxProfContext &)>;
@@ -188,26 +183,5 @@ class ProfileAnnotator {
   LLVM_ABI ~ProfileAnnotator();
 };
 
-/// Assign a GUID to functions as metadata. GUID calculation takes linkage into
-/// account, which may change especially through and after thinlto. By
-/// pre-computing and assigning as metadata, this mechanism is resilient to such
-/// changes (as well as name changes e.g. suffix ".llvm." additions).
-
-// FIXME(mtrofin): we can generalize this mechanism to calculate a GUID early in
-// the pass pipeline, associate it with any Global Value, and then use it for
-// PGO and ThinLTO.
-// At that point, this should be moved elsewhere.
-class AssignGUIDPass : public PassInfoMixin<AssignGUIDPass> {
-public:
-  explicit AssignGUIDPass() = default;
-
-  /// Assign a GUID *if* one is not already assign, as a function metadata named
-  /// `GUIDMetadataName`.
-  LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
-  LLVM_ABI static const char *GUIDMetadataName;
-  // This should become GlobalValue::getGUID
-  LLVM_ABI static uint64_t getGUID(const Function &F);
-};
-
 } // namespace llvm
 #endif // LLVM_ANALYSIS_CTXPROFANALYSIS_H
diff --git a/llvm/include/llvm/Bitcode/BitcodeReader.h b/llvm/include/llvm/Bitcode/BitcodeReader.h
index 772ca82019278..b7cab51857f0b 100644
--- a/llvm/include/llvm/Bitcode/BitcodeReader.h
+++ b/llvm/include/llvm/Bitcode/BitcodeReader.h
@@ -17,6 +17,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Bitstream/BitCodeEnums.h"
 #include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/ModuleSummaryIndex.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Error.h"
@@ -165,7 +166,8 @@ struct ParserCallbacks {
     /// into CombinedIndex.
     LLVM_ABI Error
     readSummary(ModuleSummaryIndex &CombinedIndex, StringRef ModulePath,
-                std::function<bool(GlobalValue::GUID)> IsPrevailing = nullptr);
+                std::function<bool(StringRef)> IsPrevailing = nullptr,
+                std::function<void(ValueInfo)> OnValueInfo = nullptr);
   };
 
   struct BitcodeFileContents {
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index bcf596a0d79b2..a3afad599186a 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -120,6 +120,9 @@ enum ModuleCodes {
 
   // IFUNC: [ifunc value type, addrspace, resolver val#, linkage, visibility]
   MODULE_CODE_IFUNC = 18,
+
+  // GUIDLIST: [n x i64]
+  MODULE_CODE_GUIDLIST = 19,
 };
 
 /// PARAMATTR blocks have code for defining a parameter attribute set.
diff --git a/llvm/include/llvm/IR/FixedMetadataKinds.def b/llvm/include/llvm/IR/FixedMetadataKinds.def
index 0d79677d7079e..ced586aaa503e 100644
--- a/llvm/include/llvm/IR/FixedMetadataKinds.def
+++ b/llvm/include/llvm/IR/FixedMetadataKinds.def
@@ -60,3 +60,4 @@ LLVM_FIXED_MD_KIND(MD_alloc_token, "alloc_token", 45)
 LLVM_FIXED_MD_KIND(MD_implicit_ref, "implicit.ref", 46)
 LLVM_FIXED_MD_KIND(MD_nofpclass, "nofpclass", 47)
 LLVM_FIXED_MD_KIND(MD_call_target, "call_target", 48)
+LLVM_FIXED_MD_KIND(MD_unique_id, "guid", 49)
diff --git a/llvm/include/llvm/IR/GlobalValue.h b/llvm/include/llvm/IR/GlobalValue.h
index 83e695cdd27d9..acc836e1974d4 100644
--- a/llvm/include/llvm/IR/GlobalValue.h
+++ b/llvm/include/llvm/IR/GlobalValue.h
@@ -589,17 +589,40 @@ class GlobalValue : public Constant {
   /// used as the key for a global lookup (e.g. profile or ThinLTO).
   LLVM_ABI std::string getGlobalIdentifier() const;
 
+  /// Assign a GUID to this value based on its current name and linkage.
+  /// This GUID will remain the same even if those change. This method is
+  /// idempotent -- if a GUID has already been assigned, calling it again
+  /// will do nothing.
+  ///
+  /// This is private (exposed only to \c AssignGUIDPass), as users don't need
+  /// to call it. GUIDs are assigned only by \c AssignGUIDPass. The pass
+  /// pipeline should be set up such that GUIDs are always available when
+  /// needed. If not, the GUID assignment pass should be moved (or run again)
+  /// such that they are.
+  void assignGUID();
+
+  // assignGUID needs to be accessible from AssignGUIDPass, which is called
+  // early in the pipeline to make GUIDs available to later passes. But we'd
+  // rather not expose it publicly, as no-one else should call it.
+  friend class AssignGUIDPass;
+
 public:
   /// Return a 64-bit global unique ID constructed from the name of a global
   /// symbol. Since this call doesn't supply the linkage or defining filename,
   /// the GUID computation will assume that the global has external linkage.
   LLVM_ABI static GUID getGUIDAssumingExternalLinkage(StringRef GlobalName);
 
-  /// Return a 64-bit global unique ID constructed from global value name
-  /// (i.e. returned by getGlobalIdentifier()).
-  GUID getGUID() const {
-    return getGUIDAssumingExternalLinkage(getGlobalIdentifier());
-  }
+  /// Return a 64-bit global unique ID for this value. It is based on the
+  /// "original" name and linkage of this value (i.e. whenever its GUID was
+  /// assigned). This might not match the current name and linkage.
+  GUID getGUID() const;
+
+  /// Return the GUID for this value if it has been assigned, nullopt
+  /// otherwise. This should only need to be used in some exceptional
+  /// situations. If possible whatever code needs access to a GUID should
+  /// be set up to run after AssignGUIDPass, in which case it will always
+  /// be available.
+  std::optional<GUID> getGUIDIfAssigned() const;
 
   /// @name Materialization
   /// Materialization is used to construct functions only as they're needed.
diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h
index 7156a83c9f3cc..b4a13128dd9f7 100644
--- a/llvm/include/llvm/IR/Module.h
+++ b/llvm/include/llvm/IR/Module.h
@@ -32,6 +32,7 @@
 #include "llvm/Support/CBindingWrapping.h"
 #include "llvm/Support/CodeGen.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
 #include "llvm/TargetParser/Triple.h"
 #include <cstddef>
 #include <cstdint>
@@ -576,7 +577,22 @@ class LLVM_ABI Module {
   // Use global_size() to get the total number of global variables.
   // Use globals() to get the range of all global variables.
 
+  std::optional<GlobalValue::GUID> getGUID(const Value* V) const {
+    const auto It = ValueToGUIDMap.find(V);
+    if (It == ValueToGUIDMap.end()) {
+      return {};
+    }
+
+    return It->getSecond();
+  }
+
+  void insertGUID(const Value* V, GlobalValue::GUID GUID) {
+    ValueToGUIDMap[V] = GUID;
+  }
+
 private:
+  DenseMap<const Value*, GlobalValue::GUID> ValueToGUIDMap;
+
 /// @}
 /// @name Direct access to the globals list, functions list, and symbol table
 /// @{
diff --git a/llvm/include/llvm/IR/ModuleSummaryIndex.h b/llvm/include/llvm/IR/ModuleSummaryIndex.h
index 6859b9a2f46e6..be204e8a52aa8 100644
--- a/llvm/include/llvm/IR/ModuleSummaryIndex.h
+++ b/llvm/include/llvm/IR/ModuleSummaryIndex.h
@@ -29,6 +29,7 @@
 #include "llvm/IR/Module.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
 #include "llvm/Support/InterleavedRange.h"
 #include "llvm/Support/ScaledNumber.h"
 #include "llvm/Support/StringSaver.h"
@@ -599,8 +600,8 @@ class GlobalValueSummary {
   bool wasPromoted() const { return Flags.Promoted; }
 
   void promote() {
-    assert(GlobalValue::isLocalLinkage(linkage()) &&
-           "unexpected (re-)promotion of non-local symbol");
+    assert(!GlobalValue::isExternalLinkage(linkage()) &&
+           "unexpected (re-)promotion of external symbol");
     assert(!Flags.Promoted);
     Flags.Promoted = true;
     Flags.Linkage = GlobalValue::LinkageTypes::ExternalLinkage;
@@ -1769,14 +1770,19 @@ class ModuleSummaryIndex {
     return ValueInfo(HaveGVs, VP);
   }
 
-  /// Return a ValueInfo for \p GV and mark it as belonging to GV.
-  ValueInfo getOrInsertValueInfo(const GlobalValue *GV) {
+  /// Return a ValueInfo for \p GV with GUID \p GUID and mark it as belonging to GV.
+  ValueInfo getOrInsertValueInfo(const GlobalValue *GV, GlobalValue::GUID GUID) {
     assert(HaveGVs);
-    auto VP = getOrInsertValuePtr(GV->getGUID());
+    auto VP = getOrInsertValuePtr(GUID);
     VP->second.U.GV = GV;
     return ValueInfo(HaveGVs, VP);
   }
 
+  /// Return a ValueInfo for \p GV and mark it as belonging to GV.
+  ValueInfo getOrInsertValueInfo(const GlobalValue *GV) {
+    return getOrInsertValueInfo(GV, GV->getGUID());
+  }
+
   /// Return the GUID for \p OriginalId in the OidGuidMap.
   GlobalValue::GUID getGUIDFromOriginalID(GlobalValue::GUID OriginalID) const {
     const auto I = OidGuidMap.find(OriginalID);
diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h
index 38349b604b6b3..32a47b3c87e1d 100644
--- a/llvm/include/llvm/LTO/LTO.h
+++ b/llvm/include/llvm/LTO/LTO.h
@@ -572,6 +572,23 @@ class LTO {
     /// LTO backend.
     unsigned Partition = Unknown;
 
+    // FIXME: make private, and also make GlobalResolution a class, it has been
+    // becoming more than just a data bag.
+    GlobalValue::GUID GUID = 0;
+
+    void setGUID(GlobalValue::GUID G) {
+      assert(G);
+      assert(!GUID || GUID == G);
+      GUID = G;
+    }
+
+    GlobalValue::GUID getGUID() const {
+      return GUID ? GUID
+                  : GlobalValue::getGUIDAssumingExternalLinkage(
+                        GlobalValue::getGlobalIdentifier(
+                            IRName, GlobalValue::LinkageTypes::ExternalLinkage,
+                            ""));
+    }
     /// Special partition numbers.
     enum : unsigned {
       /// A partition number has not yet been assigned to this global.
diff --git a/llvm/include/llvm/Transforms/Utils/AssignGUID.h b/llvm/include/llvm/Transforms/Utils/AssignGUID.h
new file mode 100644
index 0000000000000..0abd450d5a522
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Utils/AssignGUID.h
@@ -0,0 +1,42 @@
+//===-- AssignGUID.h - Unique identifier assignment pass --------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides a pass which assigns a a GUID (globally unique identifier)
+// to every GlobalValue in the module, according to its current name, linkage,
+// and originating file. This way we have a consistent identifier even when
+// these inputs to the GUID change (for instance, after externalising a global
+// in ThinLTO).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_ASSIGNGUID_H
+#define LLVM_TRANSFORMS_UTILS_ASSIGNGUID_H
+
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/Support/Debug.h"
+
+namespace llvm {
+
+class AssignGUIDPass : public PassInfoMixin<AssignGUIDPass> {
+public:
+  AssignGUIDPass() = default;
+
+  static void runOnModule(Module &M);
+
+  PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) {
+    AssignGUIDPass::runOnModule(M);
+    return PreservedAnalyses::all();
+  }
+
+  static bool isRequired() { return true; }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_UTILS_ASSIGNGUID_H
\ No newline at end of file
diff --git a/llvm/lib/Analysis/CtxProfAnalysis.cpp b/llvm/lib/Analysis/CtxProfAnalysis.cpp
index c4abec02e765a..d4c00e4090220 100644
--- a/llvm/lib/Analysis/CtxProfAnalysis.cpp
+++ b/llvm/lib/Analysis/CtxProfAnalysis.cpp
@@ -50,9 +50,7 @@ static cl::opt<bool> ForceIsInSpecializedModule(
     "ctx-profile-force-is-specialized", cl::init(false),
     cl::desc("Treat the given module as-if it were containing the "
              "post-thinlink module containing the root"));
-
-const char *AssignGUIDPass::GUIDMetadataName = "guid";
-
+ 
 class ProfileAnnotatorImpl final {
   friend class ProfileAnnotator;
   class BBInfo;
@@ -420,33 +418,6 @@ bool ProfileAnnotator::getOutgoingBranchWeights(
   return MaxCount > 0;
 }
 
-PreservedAnalyses AssignGUIDPass::run(Module &M, ModuleAnalysisManager &MAM) {
-  for (auto &F : M.functions()) {
-    if (F.isDeclaration())
-      continue;
-    if (F.getMetadata(GUIDMetadataName))
-      continue;
-    const GlobalValue::GUID GUID = F.getGUID();
-    F.setMetadata(GUIDMetadataName,
-                  MDNode::get(M.getContext(),
-                              {ConstantAsMetadata::get(ConstantInt::get(
-                                  Type::getInt64Ty(M.getContext()), GUID))}));
-  }
-  return PreservedAnalyses::none();
-}
-
-GlobalValue::GUID AssignGUIDPass::getGUID(const Function &F) {
-  if (F.isDeclaration()) {
-    assert(GlobalValue::isExternalLinkage(F.getLinkage()));
-    return F.getGUID();
-  }
-  auto *MD = F.getMetadata(GUIDMetadataName);
-  assert(MD && "guid not found for defined function");
-  return cast<ConstantInt>(cast<ConstantAsMetadata>(MD->getOperand(0))
-                               ->getValue()
-                               ->stripPointerCasts())
-      ->getZExtValue();
-}
 AnalysisKey CtxProfAnalysis::Key;
 
 CtxProfAnalysis::CtxProfAnalysis(std::optional<StringRef> Profile)
@@ -515,7 +486,7 @@ PGOContextualProfile CtxProfAnalysis::run(Module &M,
   for (const auto &F : M) {
     if (F.isDeclaration())
       continue;
-    auto GUID = AssignGUIDPass::getGUID(F);
+    auto GUID = F.getGUID();
     assert(GUID && "guid not found for defined function");
     const auto &Entry = F.begin();
     uint32_t MaxCounters = 0; // we expect at least a counter.
@@ -549,13 +520,6 @@ PGOContextualProfile CtxProfAnalysis::run(Module &M,
   return Result;
 }
 
-GlobalValue::GUID
-PGOContextualProfile::getDefinedFunctionGUID(const Function &F) const {
-  if (auto It = FuncInfo.find(AssignGUIDPass::getGUID(F)); It != FuncInfo.end())
-    return It->first;
-  return 0;
-}
-
 CtxProfAnalysisPrinterPass::CtxProfAnalysisPrinterPass(raw_ostream &OS)
     : OS(OS), Mode(PrintLevel) {}
 
@@ -671,7 +635,7 @@ bool PGOContextualProfile::isInSpecializedModule() const {
 
 void PGOContextualProfile::update(Visitor V, const Function &F) {
   assert(isFunctionKnown(F));
-  GlobalValue::GUID G = getDefinedFunctionGUID(F);
+  GlobalValue::GUID G = F.getGUID();
   for (auto *Node = FuncInfo.find(G)->second.Index.Next; Node;
        Node = Node->Next)
     V(*reinterpret_cast<PGOCtxProfContext *>(Node));
@@ -682,7 +646,7 @@ void PGOContextualProfile::visit(ConstVisitor V, const Function *F) const {
     return preorderVisit<const PGOCtxProfContext::CallTargetMapTy,
                          const PGOCtxProfContext>(Profiles.Contexts, V);
   assert(isFunctionKnown(*F));
-  GlobalValue::GUID G = getDefinedFunctionGUID(*F);
+  GlobalValue::GUID G = F->getGUID();
   for (const auto *Node = FuncInfo.find(G)->second.Index.Next; Node;
        Node = Node->Next)
     V(*reinterpret_cast<const PGOCtxProfContext *>(Node));
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 551b88d8b435b..fcfa2ec2be342 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -1064,8 +1064,9 @@ bool LLParser::skipModuleSummaryEntry() {
   // support is in place we will look for the tokens corresponding to the
   // expected tags.
   if (Lex.getKind() != lltok::kw_gv && Lex.getKind() != lltok::kw_module &&
-      Lex.getKind() != lltok::kw_typeid && Lex.getKind() != lltok::kw_flags &&
-      Lex.getKind() != lltok::kw_blockcount)
+      Lex.getKind() != lltok::kw_typeid &&
+      Lex.getKind() != lltok::kw_typeidCompatibleVTable &&
+      Lex.getKind() != lltok::kw_flags && Lex.getKind() != lltok::kw_blockcount)
     return tokError(
         "Expected 'gv', 'module', 'typeid', 'flags' or 'blockcount' at the "
         "start of summary entry");
@@ -9847,7 +9848,12 @@ bool LLParser::addGlobalValueToIndex(
       if (!GV)
         return error(Loc, "Reference to undefined global \"" + Name + "\"");
 
-      VI = Index->getOrInsertValueInfo(GV);
+      // Be a little lenient here, to accomodate older files without GUIDs
+      // already computed and assigned as metadata.
+      auto MaybeGUID = GV->getGUIDIfAssigned();
+      GUID = MaybeGUID ? *MaybeGUID : GlobalValue::getGUIDAssumingExternalLinkage(GV->getName());
+
+      VI = Index->getOrInsertValueInfo(GV, GUID);
     } else {
       assert(
           (!GlobalValue::isLocalLinkage(Linkage) || !SourceFileName.empty()) &&
diff --git a/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp b/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp
index 911ec7501eb8b..6574ab7a93c58 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp
@@ -142,6 +142,7 @@ GetCodeName(unsigned CodeID, unsigned BlockID,
       STRINGIFY_CODE(MODULE_CODE, METADATA_VALUES_UNUSED)
       STRINGIFY_CODE(MODULE_CODE, SOURCE_FILENAME)
       STRINGIFY_CODE(MODULE_CODE, HASH)
+      STRINGIFY_CODE(MODULE_CODE, GUIDLIST)
     }
   case bitc::IDENTIFICATION_BLOCK_ID:
     switch (CodeID) {
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 1b9f13ecec62f..2b0406f853832 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -696,6 +696,9 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
 
   std::optional<ValueTypeCallbackTy> ValueTypeCallback;
 
+  /// A list of GUIDs defined by this module. Indexed by ValueID.
+  std::vector<GlobalValue::GUID> GUIDList;
+
 public:
   BitcodeReader(BitstreamCursor Stream, StringRef Strtab,
                 StringRef ProducerIdentification, LLVMContext &Context);
@@ -974,9 +977,10 @@ class ModuleSummaryIndexBitcodeReader : public BitcodeReaderBase {
 
   /// Callback to ask whether a symbol is the prevailing copy when invoked
   /// during combined index building.
-  std::function<bool(GlobalValue::GUID)> IsPrevailing;
+  std::function<bool(StringRef)> IsPrevailing = nullptr;
+  std::function<void(ValueInfo)> OnValueInfo = nullptr;
 
-  /// Saves the stack ids from the STACK_IDS record to consult when adding stack
+  /// Saves the stack ids from the STACK_IDS record to consult when adding
   /// ids from the lists in the callsite and alloc entries to the index.
   std::vector<uint64_t> StackIds;
 
@@ -989,11 +993,15 @@ class ModuleSummaryIndexBitcodeReader : public BitcodeReaderBase {
   /// list and used to avoid repeated hash lookups.
   std::vector<unsigned> StackIdToIndex;
 
+   /// A list of GUIDs defined by this module. Indexed by ValueID.
+   std::vector<uint64_t> DefinedGUIDs;
+ 
 public:
   ModuleSummaryIndexBitcodeReader(
       BitstreamCursor Stream, StringRef Strtab, ModuleSummaryIndex &TheIndex,
       StringRef ModulePath,
-      std::function<bool(GlobalValue::GUID)> IsPrevailing = nullptr);
+      std::function<bool(StringRef)> IsPrevailing = nullptr,
+      std::function<void(ValueInfo)> OnValueInfo = nullptr);
 
   Error parseModule();
 
@@ -4040,6 +4048,14 @@ Error BitcodeReader::globalCleanup() {
     TheModule->insertGlobalVariable(Pair.second);
   }
 
+  for (size_t ValueID = 0; ValueID < GUIDList.size(); ValueID++) {
+    const auto GUID = GUIDList[ValueID];
+    if (GUID == 0) continue;
+
+    const auto* Value = ValueList[ValueID];
+    TheModule->insertGUID(Value, GUID);
+  }
+
   // Force deallocation of memory for these vectors to favor the client that
   // want lazy deserialization.
   std::vector<std::pair<GlobalVariable *, unsigned>>().swap(GlobalInits);
@@ -4843,6 +4859,10 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit,
       // historically always the start of the regular bitcode header.
       VSTOffset = Record[0] - 1;
       break;
+    // MODULE_CODE_GUIDLIST: [i64 x N]
+    case bitc::MODULE_CODE_GUIDLIST:
+      llvm::append_range(GUIDList, Record);
+      break;
     /// MODULE_CODE_SOURCE_FILENAME: [namechar x N]
     case bitc::MODULE_CODE_SOURCE_FILENAME:
       SmallString<128> ValueName;
@@ -4853,6 +4873,7 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit,
     }
     Record.clear();
   }
+
   this->ValueTypeCallback = std::nullopt;
   return Error::success();
 }
@@ -7224,9 +7245,11 @@ std::vector<StructType *> BitcodeReader::getIdentifiedStructTypes() const {
 
 ModuleSummaryIndexBitcodeReader::ModuleSummaryIndexBitcodeReader(
     BitstreamCursor Cursor, StringRef Strtab, ModuleSummaryIndex &TheIndex,
-    StringRef ModulePath, std::function<bool(GlobalValue::GUID)> IsPrevailing)
+    StringRef ModulePath, std::function<bool(StringRef)> IsPrevailing,
+    std::function<void(ValueInfo)> OnValueInfo)
     : BitcodeReaderBase(std::move(Cursor), Strtab), TheIndex(TheIndex),
-      ModulePath(ModulePath), IsPrevailing(IsPrevailing) {}
+      ModulePath(ModulePath), IsPrevailing(IsPrevailing),
+      OnValueInfo(OnValueInfo) {}
 
 void ModuleSummaryIndexBitcodeReader::addThisModule() {
   TheIndex.addModule(ModulePath);
@@ -7254,23 +7277,27 @@ ModuleSummaryIndexBitcodeReader::getValueInfoFromValueId(unsigned ValueId) {
 void ModuleSummaryIndexBitcodeReader::setValueGUID(
     uint64_t ValueID, StringRef ValueName, GlobalValue::LinkageTypes Linkage,
     StringRef SourceFileName) {
-  std::string GlobalId =
-      GlobalValue::getGlobalIdentifier(ValueName, Linkage, SourceFileName);
-  auto ValueGUID = GlobalValue::getGUIDAssumingExternalLinkage(GlobalId);
+  GlobalValue::GUID ValueGUID = 0;
+  if (ValueID < DefinedGUIDs.size())
+    ValueGUID = DefinedGUIDs[ValueID];
+  if (ValueGUID == 0)
+    ValueGUID = GlobalValue::getGUIDAssumingExternalLinkage(
+      GlobalValue::getGlobalIdentifier(ValueName, Linkage, SourceFileName));
+
   auto OriginalNameID = ValueGUID;
   if (GlobalValue::isLocalLinkage(Linkage))
     OriginalNameID = GlobalValue::getGUIDAssumingExternalLinkage(ValueName);
   if (PrintSummaryGUIDs)
-    dbgs() << "GUID " << ValueGUID << "(" << OriginalNameID << ") is "
-           << ValueName << "\n";
+    dbgs() << "GUID " << ValueGUID << "(" << OriginalNameID << ") is " << ValueName << "\n";
 
   // UseStrtab is false for legacy summary formats and value names are
   // created on stack. In that case we save the name in a string saver in
   // the index so that the value name can be recorded.
-  ValueIdToValueInfoMap[ValueID] = std::make_pair(
-      TheIndex.getOrInsertValueInfo(
-          ValueGUID, UseStrtab ? ValueName : TheIndex.saveString(ValueName)),
-      OriginalNameID);
+  auto VI = TheIndex.getOrInsertValueInfo(
+      ValueGUID, UseStrtab ? ValueName : TheIndex.saveString(ValueName));
+  ValueIdToValueInfoMap[ValueID] = std::make_pair(VI, OriginalNameID);
+  if (OnValueInfo)
+    OnValueInfo(VI);
 }
 
 // Specialized value symbol table parser used when reading module index
@@ -7479,6 +7506,10 @@ Error ModuleSummaryIndexBitcodeReader::parseModule() {
           // was historically always the start of the regular bitcode header.
           VSTOffset = Record[0] - 1;
           break;
+        // MODULE_CODE_GUIDLIST: [i64 x N]
+        case bitc::MODULE_CODE_GUIDLIST:
+          llvm::append_range(DefinedGUIDs, Record);
+          break;
         // v1 GLOBALVAR: [pointer type, isconst,     initid,       linkage, ...]
         // v1 FUNCTION:  [type,         callingconv, isproto,      linkage, ...]
         // v1 ALIAS:     [alias type,   addrspace,   aliasee val#, linkage, ...]
@@ -7875,7 +7906,7 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
       // and kept).
       auto LT = (GlobalValue::LinkageTypes)Flags.Linkage;
       bool IsPrevailingSym = !IsPrevailing || GlobalValue::isLocalLinkage(LT) ||
-                             IsPrevailing(VI.getGUID());
+                             IsPrevailing(VI.name());
 
       // If this is not the prevailing copy, and the records are in the "old"
       // order (preceding), clear them now. They should already be empty in
@@ -8691,13 +8722,14 @@ BitcodeModule::getLazyModule(LLVMContext &Context, bool ShouldLazyLoadMetadata,
 // regular LTO modules).
 Error BitcodeModule::readSummary(
     ModuleSummaryIndex &CombinedIndex, StringRef ModulePath,
-    std::function<bool(GlobalValue::GUID)> IsPrevailing) {
+    std::function<bool(StringRef)> IsPrevailing,
+    std::function<void(ValueInfo)> OnValueInfo) {
   BitstreamCursor Stream(Buffer);
   if (Error JumpFailed = Stream.JumpToBit(ModuleBit))
     return JumpFailed;
 
   ModuleSummaryIndexBitcodeReader R(std::move(Stream), Strtab, CombinedIndex,
-                                    ModulePath, IsPrevailing);
+                                    ModulePath, IsPrevailing, OnValueInfo);
   return R.parseModule();
 }
 
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 568874b145c8d..338d94639514a 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -253,6 +253,7 @@ class ModuleBitcodeWriterBase : public BitcodeWriterBase {
 
 protected:
   void writePerModuleGlobalValueSummary();
+  void writeGUIDList();
 
 private:
   void writePerModuleFunctionSummaryRecord(
@@ -1592,6 +1593,8 @@ void ModuleBitcodeWriter::writeModuleInfo() {
     Vals.clear();
   }
 
+  writeGUIDList();
+
   // Emit the global variable information.
   for (const GlobalVariable &GV : M.globals()) {
     unsigned AbbrevToUse = 0;
@@ -4587,12 +4590,21 @@ void ModuleBitcodeWriterBase::writePerModuleFunctionSummaryRecord(
       /*WriteContextSizeInfoIndex*/ true, CallStackPos, CallStackCount);
 }
 
+static GlobalValue::GUID getOrComputeGUID(const GlobalValue& V) {
+  auto MaybeGUID = V.getGUIDIfAssigned();
+  return MaybeGUID ? *MaybeGUID : GlobalValue::getGUIDAssumingExternalLinkage(V.getName());
+}
+
 // Collect the global value references in the given variable's initializer,
 // and emit them in a summary record.
 void ModuleBitcodeWriterBase::writeModuleLevelReferences(
     const GlobalVariable &V, SmallVector<uint64_t, 64> &NameVals,
     unsigned FSModRefsAbbrev, unsigned FSModVTableRefsAbbrev) {
-  auto VI = Index->getValueInfo(V.getGUID());
+  // Be a little lenient here, to accomodate older files without GUIDs
+  // already computed and assigned as metadata.
+  GlobalValue::GUID GUID = getOrComputeGUID(V);
+
+  auto VI = Index->getValueInfo(GUID);
   if (!VI || VI.getSummaryList().empty()) {
     // Only declarations should not have a summary (a declaration might however
     // have a summary if the def was in module level asm).
@@ -4805,7 +4817,11 @@ void ModuleBitcodeWriterBase::writePerModuleGlobalValueSummary() {
     if (!F.hasName())
       report_fatal_error("Unexpected anonymous function when writing summary");
 
-    ValueInfo VI = Index->getValueInfo(F.getGUID());
+    // Be a little lenient here, to accomodate older files without GUIDs
+    // already computed and assigned as metadata.
+    GlobalValue::GUID GUID = getOrComputeGUID(F);
+
+    ValueInfo VI = Index->getValueInfo(GUID);
     if (!VI || VI.getSummaryList().empty()) {
       // Only declarations should not have a summary (a declaration might
       // however have a summary if the def was in module level asm).
@@ -4837,7 +4853,9 @@ void ModuleBitcodeWriterBase::writePerModuleGlobalValueSummary() {
     if (!F.hasName())
       report_fatal_error("Unexpected anonymous function when writing summary");
 
-    ValueInfo VI = Index->getValueInfo(F.getGUID());
+    GlobalValue::GUID GUID = getOrComputeGUID(F);
+
+    ValueInfo VI = Index->getValueInfo(GUID);
     if (!VI || VI.getSummaryList().empty()) {
       // Only declarations should not have a summary (a declaration might
       // however have a summary if the def was in module level asm).
@@ -4889,6 +4907,27 @@ void ModuleBitcodeWriterBase::writePerModuleGlobalValueSummary() {
   Stream.ExitBlock();
 }
 
+void ModuleBitcodeWriterBase::writeGUIDList() {
+  const ValueEnumerator::ValueList &Vals = VE.getValues();
+  const size_t Max = Vals.size();
+
+  std::vector<GlobalValue::GUID> GUIDs(Max, 0);
+  for (const GlobalValue &GV : M.global_values()) {
+    GlobalValue::GUID GUID;
+    if (auto MaybeGUID = GV.getGUIDIfAssigned(); MaybeGUID) {
+      GUID = *MaybeGUID;
+    } else {
+      GUID = 0;
+    }
+    if (GUID == 0) continue;
+
+    const auto ValueID = VE.getValueID(&GV);
+    GUIDs[ValueID] = GUID;
+  }
+
+  Stream.EmitRecord(bitc::MODULE_CODE_GUIDLIST, GUIDs);
+}
+
 /// Emit the combined summary section into the combined index file.
 void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
   Stream.EnterSubblock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID, 4);
@@ -5681,6 +5720,8 @@ void ThinLinkBitcodeWriter::writeSimplifiedModuleInfo() {
     Vals.clear();
   }
 
+  writeGUIDList();
+
   // Emit the global variable information.
   for (const GlobalVariable &GV : M.globals()) {
     // GLOBALVAR: [strtab offset, strtab size, 0, 0, 0, linkage]
diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp
index 844266c72d773..b62ad1ccb26a6 100644
--- a/llvm/lib/IR/Globals.cpp
+++ b/llvm/lib/IR/Globals.cpp
@@ -79,6 +79,48 @@ GlobalValue::getGUIDAssumingExternalLinkage(StringRef GlobalIdentifier) {
   return MD5Hash(GlobalIdentifier);
 }
 
+void GlobalValue::assignGUID() {
+  if (getMetadata(LLVMContext::MD_unique_id) != nullptr)
+    return;
+
+  const GUID G =
+      GlobalValue::getGUIDAssumingExternalLinkage(getGlobalIdentifier());
+  setMetadata(
+      LLVMContext::MD_unique_id,
+      MDNode::get(getContext(), {ConstantAsMetadata::get(ConstantInt::get(
+                                    Type::getInt64Ty(getContext()), G))}));
+}
+
+GlobalValue::GUID GlobalValue::getGUID() const {
+  auto MaybeGUID = getGUIDIfAssigned();
+  assert(MaybeGUID.has_value() &&
+         "GUID was not assigned before calling GetGUID()");
+  return *MaybeGUID;
+}
+
+std::optional<GlobalValue::GUID> GlobalValue::getGUIDIfAssigned() const {
+  // First check the metadata.
+  auto *MD = getMetadata(LLVMContext::MD_unique_id);
+  if (MD != nullptr)
+    return cast<ConstantInt>(cast<ConstantAsMetadata>(MD->getOperand(0))
+                                ->getValue()
+                                ->stripPointerCasts())
+        ->getZExtValue();
+
+  // Handle a few special cases where we just want to compute it based on the
+  // current properties.
+  if (isDeclaration() || isa<GlobalAlias>(this) || getName().starts_with("llvm.")) {
+    return GlobalValue::getGUIDAssumingExternalLinkage(getGlobalIdentifier());
+  }
+  
+  // Otherwise we try to look it up in the module, for cases where we've read
+  // the GUID table but not the metadata.
+  if (getParent() == nullptr) return {};
+  const Module &M = *getParent();
+
+  return M.getGUID(this);
+}
+
 void GlobalValue::removeFromParent() {
   switch (getValueID()) {
 #define HANDLE_GLOBAL_VALUE(NAME)                                              \
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index 36360081fa4a0..4c6a3f874121f 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -27,6 +27,7 @@
 #include "llvm/Config/llvm-config.h"
 #include "llvm/IR/AutoUpgrade.h"
 #include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/IR/GlobalValue.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/LLVMRemarkStreamer.h"
 #include "llvm/IR/LegacyPassManager.h"
@@ -752,6 +753,7 @@ void LTO::addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
     // FIXME: instead of this check, it would be desirable to compute GUIDs
     // based on mangled name, but this requires an access to the Target Triple
     // and would be relatively invasive on the codebase.
+    // FIXME: use the GUID member of GlobalRes.
     if (GlobalRes.IRName != Sym.getIRName()) {
       GlobalRes.Partition = GlobalResolution::External;
       GlobalRes.VisibleOutsideSummary = true;
@@ -1163,21 +1165,27 @@ LTO::addThinLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
   llvm::TimeTraceScope timeScope("LTO add thin LTO");
   const auto BMID = BM.getModuleIdentifier();
   ArrayRef<SymbolResolution> ResTmp = Res;
+  DenseSet<StringRef> Prevailing;
   for (const InputFile::Symbol &Sym : Syms) {
     assert(!ResTmp.empty());
     const SymbolResolution &R = ResTmp.consume_front();
-
-    if (!Sym.getIRName().empty() && R.Prevailing) {
-      auto GUID = GlobalValue::getGUIDAssumingExternalLinkage(
-          GlobalValue::getGlobalIdentifier(Sym.getIRName(),
-                                           GlobalValue::ExternalLinkage, ""));
-      ThinLTO.setPrevailingModuleForGUID(GUID, BMID);
-    }
+    if (!Sym.getIRName().empty() && R.Prevailing)
+      Prevailing.insert(Sym.getIRName());
   }
 
+  StringMap<GlobalValue::GUID> IRSpecifiedGUIDs;
   if (Error Err = BM.readSummary(
-          ThinLTO.CombinedIndex, BMID, [&](GlobalValue::GUID GUID) {
-            return ThinLTO.isPrevailingModuleForGUID(GUID, BMID);
+          ThinLTO.CombinedIndex, BMID,
+          [&](StringRef Name) { return (Prevailing.count(Name) > 0); },
+          [&](ValueInfo VI) {
+            auto IT = IRSpecifiedGUIDs.insert({VI.name(), VI.getGUID()});
+            (void)IT;
+            assert(IT.second);
+            if (auto GRIt = GlobalResolutions->find(VI.name());
+                GRIt != GlobalResolutions->end() &&
+                Prevailing.count(VI.name())) {
+              GRIt->second.setGUID(VI.getGUID());
+            }
           }))
     return Err;
   LLVM_DEBUG(dbgs() << "Module " << BMID << "\n");
@@ -1185,28 +1193,31 @@ LTO::addThinLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
   for (const InputFile::Symbol &Sym : Syms) {
     assert(!Res.empty());
     const SymbolResolution &R = Res.consume_front();
-
+    auto GUIDIter = IRSpecifiedGUIDs.find(Sym.getIRName());
+    auto GUID =
+        GUIDIter == IRSpecifiedGUIDs.end()
+            ? GlobalValue::getGUIDAssumingExternalLinkage(
+                  GlobalValue::getGlobalIdentifier(
+                      Sym.getIRName(), GlobalValue::ExternalLinkage, ""))
+            : GUIDIter->second;
     if (!Sym.getIRName().empty() &&
         (R.Prevailing || R.FinalDefinitionInLinkageUnit)) {
-      auto GUID = GlobalValue::getGUIDAssumingExternalLinkage(
-          GlobalValue::getGlobalIdentifier(Sym.getIRName(),
-                                           GlobalValue::ExternalLinkage, ""));
       if (R.Prevailing) {
-        assert(ThinLTO.isPrevailingModuleForGUID(GUID, BMID));
-
+        ThinLTO.setPrevailingModuleForGUID(GUID, BMID);
         // For linker redefined symbols (via --wrap or --defsym) we want to
         // switch the linkage to `weak` to prevent IPOs from happening.
         // Find the summary in the module for this very GV and record the new
         // linkage so that we can switch it when we import the GV.
         if (R.LinkerRedefined)
-          if (auto S = ThinLTO.CombinedIndex.findSummaryInModule(GUID, BMID))
+          if (auto *S = ThinLTO.CombinedIndex.findSummaryInModule(
+                  GUID, BMID))
             S->setLinkage(GlobalValue::WeakAnyLinkage);
       }
 
       // If the linker resolved the symbol to a local definition then mark it
       // as local in the summary for the module we are adding.
       if (R.FinalDefinitionInLinkageUnit) {
-        if (auto S = ThinLTO.CombinedIndex.findSummaryInModule(GUID, BMID)) {
+        if (auto *S = ThinLTO.CombinedIndex.findSummaryInModule(GUID, BMID)) {
           S->setDSOLocal(true);
         }
       }
@@ -1301,8 +1312,7 @@ Error LTO::run(AddStreamFn AddStream, FileCache Cache) {
     if (Res.second.IRName.empty())
       continue;
 
-    GlobalValue::GUID GUID = GlobalValue::getGUIDAssumingExternalLinkage(
-        GlobalValue::dropLLVMManglingEscape(Res.second.IRName));
+    GlobalValue::GUID GUID = Res.second.getGUID();
 
     if (Res.second.VisibleOutsideSummary && Res.second.Prevailing)
       GUIDPreservedSymbols.insert(GUID);
@@ -2103,8 +2113,7 @@ Error LTO::runThinLTO(AddStreamFn AddStream, FileCache Cache,
     if (Res.second.Partition != GlobalResolution::External ||
         !Res.second.isPrevailingIRSymbol())
       continue;
-    auto GUID = GlobalValue::getGUIDAssumingExternalLinkage(
-        GlobalValue::dropLLVMManglingEscape(Res.second.IRName));
+    auto GUID = Res.second.getGUID();
     // Mark exported unless index-based analysis determined it to be dead.
     if (ThinLTO.CombinedIndex.isGUIDLive(GUID))
       ExportedGUIDs.insert(GUID);
diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index 7ee2557a68bd5..0373af7dfee8c 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -606,12 +606,17 @@ static void dropDeadSymbols(Module &Mod, const GVSummaryMapTy &DefinedGlobals,
                             const ModuleSummaryIndex &Index) {
   llvm::TimeTraceScope timeScope("Drop dead symbols");
   std::vector<GlobalValue*> DeadGVs;
-  for (auto &GV : Mod.global_values())
-    if (GlobalValueSummary *GVS = DefinedGlobals.lookup(GV.getGUID()))
+
+  for (auto &GV : Mod.global_values()) {
+    auto GUID = Mod.getGUID(&GV);
+    if (!GUID) continue;
+
+    if (GlobalValueSummary *GVS = DefinedGlobals.lookup(*GUID))
       if (!Index.isGlobalValueLive(GVS)) {
         DeadGVs.push_back(&GV);
         convertToDeclaration(GV);
       }
+  }
 
   // Now that all dead bodies have been dropped, delete the actual objects
   // themselves when possible.
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 78e4c73ef0d2b..1fa04a5216b20 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -345,6 +345,7 @@
 #include "llvm/Transforms/Scalar/TailRecursionElimination.h"
 #include "llvm/Transforms/Scalar/WarnMissedTransforms.h"
 #include "llvm/Transforms/Utils/AddDiscriminators.h"
+#include "llvm/Transforms/Utils/AssignGUID.h"
 #include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
 #include "llvm/Transforms/Utils/BreakCriticalEdges.h"
 #include "llvm/Transforms/Utils/CanonicalizeAliases.h"
diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp
index 123541a985454..f2c75c37a86e0 100644
--- a/llvm/lib/Passes/PassBuilderPipelines.cpp
+++ b/llvm/lib/Passes/PassBuilderPipelines.cpp
@@ -135,6 +135,7 @@
 #include "llvm/Transforms/Scalar/TailRecursionElimination.h"
 #include "llvm/Transforms/Scalar/WarnMissedTransforms.h"
 #include "llvm/Transforms/Utils/AddDiscriminators.h"
+#include "llvm/Transforms/Utils/AssignGUID.h"
 #include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
 #include "llvm/Transforms/Utils/CanonicalizeAliases.h"
 #include "llvm/Transforms/Utils/CountVisits.h"
@@ -812,6 +813,7 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level,
 void PassBuilder::addRequiredLTOPreLinkPasses(ModulePassManager &MPM) {
   MPM.addPass(CanonicalizeAliasesPass());
   MPM.addPass(NameAnonGlobalPass());
+  MPM.addPass(AssignGUIDPass());
 }
 
 void PassBuilder::addPreInlinerPasses(ModulePassManager &MPM,
@@ -1070,6 +1072,7 @@ PassBuilder::buildModuleInlinerPipeline(OptimizationLevel Level,
   if (!UseCtxProfile.empty() && Phase == ThinOrFullLTOPhase::ThinLTOPostLink) {
     MPM.addPass(GlobalOptPass());
     MPM.addPass(GlobalDCEPass());
+    MPM.addPass(AssignGUIDPass());
     MPM.addPass(PGOCtxProfFlatteningPass(/*IsPreThinlink=*/false));
   }
 
@@ -1262,10 +1265,8 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
     // In pre-link, we just want the instrumented IR. We use the contextual
     // profile in the post-thinlink phase.
     // The instrumentation will be removed in post-thinlink after IPO.
-    // FIXME(mtrofin): move AssignGUIDPass if there is agreement to use this
-    // mechanism for GUIDs.
-    MPM.addPass(AssignGUIDPass());
     if (IsCtxProfUse) {
+      MPM.addPass(AssignGUIDPass());
       MPM.addPass(PGOCtxProfFlatteningPass(/*IsPreThinlink=*/true));
       return MPM;
     }
@@ -1686,6 +1687,8 @@ PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
   if (PTO.DevirtualizeSpeculatively && LTOPhase == ThinOrFullLTOPhase::None) {
     // TODO: explore a better pipeline configuration that can improve
     // compilation time overhead.
+    // FIXME: move this earlier (lots of pass ordering tests will need fixing)
+    MPM.addPass(AssignGUIDPass());
     MPM.addPass(WholeProgramDevirtPass(
         /*ExportSummary*/ nullptr,
         /*ImportSummary*/ nullptr,
diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp
index 4d4b32749a045..a1c7c664ee947 100644
--- a/llvm/lib/Transforms/IPO/FunctionImport.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp
@@ -12,6 +12,7 @@
 
 #include "llvm/Transforms/IPO/FunctionImport.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
@@ -1878,6 +1879,21 @@ static void internalizeGVsAfterImport(Module &M) {
     }
 }
 
+static GlobalValue::GUID getGUIDOrFallback(const GlobalValue& GV) {
+    // Modules compiled against the current version should have a GUID table
+    // and hence have the GUID available simply by calling getGUID(). But we
+    // want to support running on old bitcode files which have no embedded
+    // GUIDs. So if it's missing we fall back to computing the GUID with its
+    // current name / linkage type.
+    const auto MaybeGUID = GV.getGUIDIfAssigned();
+    return MaybeGUID ? *MaybeGUID
+        : GlobalValue::getGUIDAssumingExternalLinkage(
+            GlobalValue::getGlobalIdentifier(
+              GV.getName(),
+              GV.getLinkage(),
+              GV.getParent()->getSourceFileName()));
+}
+
 // Automatically import functions in Module \p DestModule based on the summaries
 // index.
 Expected<bool> FunctionImporter::importFunctions(
@@ -1892,7 +1908,7 @@ Expected<bool> FunctionImporter::importFunctions(
   DenseSet<GlobalValue::GUID> MoveSymbolGUIDSet;
   MoveSymbolGUIDSet.insert_range(MoveSymbolGUID);
   for (auto &F : DestModule)
-    if (!F.isDeclaration() && MoveSymbolGUIDSet.contains(F.getGUID()))
+    if (!F.isDeclaration() && MoveSymbolGUIDSet.contains(getGUIDOrFallback(F)))
       F.deleteBody();
 
   IRMover Mover(DestModule);
@@ -1920,7 +1936,7 @@ Expected<bool> FunctionImporter::importFunctions(
       for (Function &F : *SrcModule) {
         if (!F.hasName())
           continue;
-        auto GUID = F.getGUID();
+        auto GUID = getGUIDOrFallback(F);
         auto MaybeImportType = ImportList.getImportType(ModName, GUID);
         bool ImportDefinition =
             MaybeImportType == GlobalValueSummary::Definition;
@@ -1960,7 +1976,7 @@ Expected<bool> FunctionImporter::importFunctions(
       for (GlobalVariable &GV : SrcModule->globals()) {
         if (!GV.hasName())
           continue;
-        auto GUID = GV.getGUID();
+        auto GUID = getGUIDOrFallback(GV);
         auto MaybeImportType = ImportList.getImportType(ModName, GUID);
         bool ImportDefinition =
             MaybeImportType == GlobalValueSummary::Definition;
@@ -1984,29 +2000,31 @@ Expected<bool> FunctionImporter::importFunctions(
       for (GlobalAlias &GA : SrcModule->aliases()) {
         if (!GA.hasName() || isa<GlobalIFunc>(GA.getAliaseeObject()))
           continue;
-        auto GUID = GA.getGUID();
+        auto GUID = getGUIDOrFallback(GA);
         auto MaybeImportType = ImportList.getImportType(ModName, GUID);
         bool ImportDefinition =
             MaybeImportType == GlobalValueSummary::Definition;
 
-        LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not")
-                          << " importing alias"
-                          << (ImportDefinition
-                                  ? " definition "
-                                  : (MaybeImportType ? " declaration " : " "))
-                          << GUID << " " << GA.getName() << " from "
+       LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not")
+                         << " importing alias"
+                         << (ImportDefinition
+                                 ? " definition "
+                                 : (MaybeImportType ? " declaration " : " "))
+                         << GUID << " " << GA.getName() << " from "
+                         << SrcModule->getSourceFileName() << "\n");
+       if (ImportDefinition) {
+         if (Error Err = GA.materialize())
+           return std::move(Err);
+         // Import alias as a copy of its aliasee.
+         GlobalObject *GO = GA.getAliaseeObject();
+         if (Error Err = GO->materialize())
+           return std::move(Err);
+         auto *Fn = replaceAliasWithAliasee(SrcModule.get(), &GA);
+         assert(Fn);
+         (void)Fn;
+         LLVM_DEBUG(dbgs() << "Is importing aliasee fn " << getGUIDOrFallback(*GO) << " "
+                           << GO->getName() << " from "
                           << SrcModule->getSourceFileName() << "\n");
-        if (ImportDefinition) {
-          if (Error Err = GA.materialize())
-            return std::move(Err);
-          // Import alias as a copy of its aliasee.
-          GlobalObject *GO = GA.getAliaseeObject();
-          if (Error Err = GO->materialize())
-            return std::move(Err);
-          auto *Fn = replaceAliasWithAliasee(SrcModule.get(), &GA);
-          LLVM_DEBUG(dbgs() << "Is importing aliasee fn " << GO->getGUID()
-                            << " " << GO->getName() << " from "
-                            << SrcModule->getSourceFileName() << "\n");
           if (EnableImportMetadata || EnableMemProfContextDisambiguation) {
             // Add 'thinlto_src_module' and 'thinlto_src_file' metadata for
             // statistics and debugging.
diff --git a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
index fb9969620f7f8..9bb93d7c160f5 100644
--- a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
+++ b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
@@ -198,6 +198,8 @@ void simplifyExternals(Module &M) {
                                            AttributeList::FunctionIndex,
                                            F.getAttributes().getFnAttrs()));
     NewF->takeName(&F);
+    NewF->setMetadata(LLVMContext::MD_unique_id,
+                      F.getMetadata(LLVMContext::MD_unique_id));
     F.replaceAllUsesWith(NewF);
     F.eraseFromParent();
   }
diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
index e057761256775..d2af603c079c1 100644
--- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
+++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
@@ -108,6 +108,7 @@
 #include "llvm/TargetParser/Triple.h"
 #include "llvm/Transforms/IPO.h"
 #include "llvm/Transforms/IPO/FunctionAttrs.h"
+#include "llvm/Transforms/Utils/AssignGUID.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Transforms/Utils/CallPromotionUtils.h"
 #include "llvm/Transforms/Utils/Evaluator.h"
@@ -886,6 +887,12 @@ void llvm::updateVCallVisibilityInModule(
     function_ref<bool(StringRef)> IsVisibleToRegularObj) {
   if (!hasWholeProgramVisibility(WholeProgramVisibilityEnabledInLTO))
     return;
+
+  // Manually assign GUIDs -- updateVCallVisibilityInModule accesses GUIDs, and
+  // there's no way to specify it in the pass pipeline since this runs before
+  // any pass given on the command line.
+  AssignGUIDPass::runOnModule(M);
+
   for (GlobalVariable &GV : M.globals()) {
     // Add linkage unit visibility to any variable with type metadata, which are
     // the vtable definitions. We won't have an existing vcall_visibility
diff --git a/llvm/lib/Transforms/Instrumentation/PGOCtxProfFlattening.cpp b/llvm/lib/Transforms/Instrumentation/PGOCtxProfFlattening.cpp
index 32ae14b45764b..42609f29df625 100644
--- a/llvm/lib/Transforms/Instrumentation/PGOCtxProfFlattening.cpp
+++ b/llvm/lib/Transforms/Instrumentation/PGOCtxProfFlattening.cpp
@@ -126,7 +126,7 @@ void annotateIndirectCalls(Module &M, const CtxProfAnalysis::Result &CtxProf) {
   for (auto &F : M) {
     if (F.isDeclaration())
       continue;
-    auto FlatProfIter = FlatIndCalls.find(AssignGUIDPass::getGUID(F));
+    auto FlatProfIter = FlatIndCalls.find(F.getGUID());
     if (FlatProfIter == FlatIndCalls.end())
       continue;
     const auto &FlatProf = FlatProfIter->second;
@@ -179,7 +179,7 @@ PreservedAnalyses PGOCtxProfFlatteningPass::run(Module &M,
            "Function has unreachable basic blocks. The expectation was that "
            "DCE was run before.");
 
-    auto It = FlattenedProfile.find(AssignGUIDPass::getGUID(F));
+    auto It = FlattenedProfile.find(F.getGUID());
     // If this function didn't appear in the contextual profile, it's cold.
     if (It == FlattenedProfile.end())
       clearColdFunctionProfile(F);
diff --git a/llvm/lib/Transforms/Instrumentation/PGOCtxProfLowering.cpp b/llvm/lib/Transforms/Instrumentation/PGOCtxProfLowering.cpp
index de7c1696078db..6a9d10ef5cca0 100644
--- a/llvm/lib/Transforms/Instrumentation/PGOCtxProfLowering.cpp
+++ b/llvm/lib/Transforms/Instrumentation/PGOCtxProfLowering.cpp
@@ -280,8 +280,7 @@ bool CtxInstrumentationLowerer::lowerFunction(Function &F) {
       assert(Mark->getIndex()->isZero());
 
       IRBuilder<> Builder(Mark);
-      Guid = Builder.getInt64(
-          AssignGUIDPass::getGUID(cast<Function>(*Mark->getNameValue())));
+      Guid = Builder.getInt64(cast<Function>(*Mark->getNameValue()).getGUID());
       // The type of the context of this function is now knowable since we have
       // NumCallsites and NumCounters. We declare it here because it's more
       // convenient - we have the Builder.
diff --git a/llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp b/llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp
index f926bafbe8b2c..bab353682382a 100644
--- a/llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp
+++ b/llvm/lib/Transforms/Scalar/JumpTableToSwitch.cpp
@@ -12,7 +12,6 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Analysis/ConstantFolding.h"
-#include "llvm/Analysis/CtxProfAnalysis.h"
 #include "llvm/Analysis/DomTreeUpdater.h"
 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
 #include "llvm/Analysis/PostDominators.h"
@@ -212,8 +211,8 @@ PreservedAnalyses JumpTableToSwitchPass::run(Function &F,
   DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
   bool Changed = false;
   auto FuncToGuid = [&](const Function &Fct) {
-    if (Fct.getMetadata(AssignGUIDPass::GUIDMetadataName))
-      return AssignGUIDPass::getGUID(Fct);
+    if (const auto MaybeGUID = Fct.getGUIDIfAssigned(); MaybeGUID)
+      return *MaybeGUID;
 
     return Function::getGUIDAssumingExternalLinkage(getIRPGOFuncName(F, InLTO));
   };
diff --git a/llvm/lib/Transforms/Utils/AssignGUID.cpp b/llvm/lib/Transforms/Utils/AssignGUID.cpp
new file mode 100644
index 0000000000000..7a7dba15c64fb
--- /dev/null
+++ b/llvm/lib/Transforms/Utils/AssignGUID.cpp
@@ -0,0 +1,31 @@
+//===-- AssignGUID.cpp - Unique identifier assignment pass ------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides a pass which assigns a a GUID (globally unique identifier)
+// to every GlobalValue in the module, according to its current name, linkage,
+// and originating file.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Utils/AssignGUID.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+
+void AssignGUIDPass::runOnModule(Module &M) {
+  for (auto &GV : M.globals()) {
+    if (GV.isDeclaration())
+      continue;
+    GV.assignGUID();
+  }
+  for (auto &F : M.functions()) {
+    if (F.isDeclaration())
+      continue;
+    F.assignGUID();
+  }
+}
\ No newline at end of file
diff --git a/llvm/lib/Transforms/Utils/CMakeLists.txt b/llvm/lib/Transforms/Utils/CMakeLists.txt
index 2b5f5cf344e60..3541af676fc31 100644
--- a/llvm/lib/Transforms/Utils/CMakeLists.txt
+++ b/llvm/lib/Transforms/Utils/CMakeLists.txt
@@ -2,6 +2,7 @@ add_llvm_component_library(LLVMTransformUtils
   AddDiscriminators.cpp
   AMDGPUEmitPrintf.cpp
   ASanStackFrameLayout.cpp
+  AssignGUID.cpp
   AssumeBundleBuilder.cpp
   BasicBlockUtils.cpp
   BreakCriticalEdges.cpp
diff --git a/llvm/lib/Transforms/Utils/CallPromotionUtils.cpp b/llvm/lib/Transforms/Utils/CallPromotionUtils.cpp
index f0f9add09bf82..6912338ce5ffd 100644
--- a/llvm/lib/Transforms/Utils/CallPromotionUtils.cpp
+++ b/llvm/lib/Transforms/Utils/CallPromotionUtils.cpp
@@ -616,11 +616,11 @@ CallBase *llvm::promoteCallWithIfThenElse(CallBase &CB, Function &Callee,
   IndirectBBIns->setIndex(IndirectID);
   IndirectBBIns->insertInto(&IndirectBB, IndirectBB.getFirstInsertionPt());
 
-  const GlobalValue::GUID CalleeGUID = AssignGUIDPass::getGUID(Callee);
+  const GlobalValue::GUID CalleeGUID = Callee.getGUID();
   const uint32_t NewCountersSize = IndirectID + 1;
 
   auto ProfileUpdater = [&](PGOCtxProfContext &Ctx) {
-    assert(Ctx.guid() == AssignGUIDPass::getGUID(Caller));
+    assert(Ctx.guid() == Caller.getGUID());
     assert(NewCountersSize - 2 == Ctx.counters().size());
     // All the ctx-es belonging to a function must have the same size counters.
     Ctx.resizeCounters(NewCountersSize);
@@ -655,7 +655,6 @@ CallBase *llvm::promoteCallWithIfThenElse(CallBase &CB, Function &Callee,
     // times, and the indirect BB, IndirectCount times
     Ctx.counters()[DirectID] = DirectCount;
     Ctx.counters()[IndirectID] = IndirectCount;
-
   };
   CtxProf.update(ProfileUpdater, Caller);
   return &DirectCall;
diff --git a/llvm/lib/Transforms/Utils/CloneModule.cpp b/llvm/lib/Transforms/Utils/CloneModule.cpp
index bb638f180bfbf..6768f6fff580a 100644
--- a/llvm/lib/Transforms/Utils/CloneModule.cpp
+++ b/llvm/lib/Transforms/Utils/CloneModule.cpp
@@ -129,17 +129,21 @@ std::unique_ptr<Module> llvm::CloneModule(
   for (const Function &I : M) {
     Function *F = cast<Function>(VMap[&I]);
 
-    if (I.isDeclaration()) {
+    auto CopyMD = [&]() {
       // Copy over metadata for declarations since we're not doing it below in
       // CloneFunctionInto().
       SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;
       I.getAllMetadata(MDs);
       for (auto MD : MDs)
         F->addMetadata(MD.first, *MapMetadata(MD.second, VMap));
+    };
+    if (I.isDeclaration()) {
+      CopyMD();
       continue;
     }
 
     if (!ShouldCloneDefinition(&I)) {
+      CopyMD();            
       // Skip after setting the correct linkage for an external reference.
       F->setLinkage(GlobalValue::ExternalLinkage);
       // Personality function is not valid on a declaration.
diff --git a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
index 475699c42b21e..72f9b7be7f432 100644
--- a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
+++ b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
@@ -166,6 +166,21 @@ FunctionImportGlobalProcessing::getPromotedName(const GlobalValue *SGV) {
       ImportIndex.getModuleHash(SGV->getParent()->getModuleIdentifier()));
 }
 
+static GlobalValue::GUID getGUIDOrFallback(const GlobalValue& GV) {
+    // Modules compiled against the current version should have a GUID table
+    // and hence have the GUID available simply by calling getGUID(). But we
+    // want to support running on old bitcode files which have no embedded
+    // GUIDs. So if it's missing we fall back to computing the GUID with its
+    // current name / linkage type.
+    const auto MaybeGUID = GV.getGUIDIfAssigned();
+    return MaybeGUID ? *MaybeGUID
+        : GlobalValue::getGUIDAssumingExternalLinkage(
+            GlobalValue::getGlobalIdentifier(
+              GV.getName(),
+              GV.getLinkage(),
+              GV.getParent()->getSourceFileName()));
+}
+
 GlobalValue::LinkageTypes
 FunctionImportGlobalProcessing::getLinkage(const GlobalValue *SGV,
                                            bool DoPromote) {
@@ -191,7 +206,7 @@ FunctionImportGlobalProcessing::getLinkage(const GlobalValue *SGV,
     // and/or optimization, but are turned into declarations later
     // during the EliminateAvailableExternally pass.
     if (doImportAsDefinition(SGV) && !isa<GlobalAlias>(SGV))
-      return SymbolsToMove.contains(SGV->getGUID())
+      return SymbolsToMove.contains(getGUIDOrFallback(*SGV))
                  ? GlobalValue::ExternalLinkage
                  : GlobalValue::AvailableExternallyLinkage;
     // An imported external declaration stays external.
@@ -267,7 +282,7 @@ void FunctionImportGlobalProcessing::processGlobalForThinLTO(GlobalValue &GV) {
 
   ValueInfo VI;
   if (GV.hasName())
-    VI = ImportIndex.getValueInfo(GV.getGUID());
+    VI = ImportIndex.getValueInfo(getGUIDOrFallback(GV));
 
   // We should always have a ValueInfo (i.e. GV in index) for definitions when
   // we are exporting, and also when importing that value.
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp
index a779a25f7378e..e8dce4505b219 100644
--- a/llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -2385,7 +2385,7 @@ llvm::InlineResult llvm::InlineFunction(
   // Get some preliminary data about the callsite before it might get inlined.
   // Inlining shouldn't delete the callee, but it's cleaner (and low-cost) to
   // get this data upfront and rely less on InlineFunction's behavior.
-  const auto CalleeGUID = AssignGUIDPass::getGUID(Callee);
+  const auto CalleeGUID = Callee.getGUID();
   auto *CallsiteIDIns = CtxProfAnalysis::getCallsiteInstrumentation(CB);
   const auto CallsiteID =
       static_cast<uint32_t>(CallsiteIDIns->getIndex()->getZExtValue());
@@ -2410,7 +2410,7 @@ llvm::InlineResult llvm::InlineFunction(
   const uint32_t NewCountersSize = CtxProf.getNumCounters(Caller);
 
   auto Updater = [&](PGOCtxProfContext &Ctx) {
-    assert(Ctx.guid() == AssignGUIDPass::getGUID(Caller));
+    assert(Ctx.guid() == Caller.getGUID());
     const auto &[CalleeCounterMap, CalleeCallsiteMap] = IndicesMaps;
     assert(
         (Ctx.counters().size() +
diff --git a/llvm/test/Assembler/index-value-order.ll b/llvm/test/Assembler/index-value-order.ll
index 9df6d4a46fef2..15ace18647de6 100644
--- a/llvm/test/Assembler/index-value-order.ll
+++ b/llvm/test/Assembler/index-value-order.ll
@@ -11,13 +11,16 @@ target triple = "x86_64-unknown-linux-gnu"
 
 $_ZTSN3FooE = comdat any
 
- at _ZTSN3FooE = linkonce_odr constant [7 x i8] c"N3FooE\00", comdat, align 1
-@"_ZTVN3FooE" = internal unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr null, ptr @"_Z3barv"] }, align 8
+ at _ZTSN3FooE = linkonce_odr constant [7 x i8] c"N3FooE\00", comdat, align 1, !guid !0
+@"_ZTVN3FooE" = internal unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr null, ptr @"_Z3barv"] }, align 8, !guid !1
 
-define internal i32 @"_Z3barv"() {
+define internal i32 @"_Z3barv"() !guid !2 {
   ret i32 0
 }
 
+!0 = !{i64 0}
+!1 = !{i64 1}
+!2 = !{i64 2}
 ^0 = module: (path: "index-value-order.ll", hash: (0, 0, 0, 0, 0))
 ^9 = gv: (name: "_ZTVN3FooE", summaries: (variable: (module: ^0, flags: (linkage: internal, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 1, canAutoHide: 0), varFlags: (readonly: 1, writeonly: 0, constant: 1, vcall_visibility: 0), vTableFuncs: ((virtFunc: ^3, offset: 16)))))
 ^4 = gv: (name: "_ZTSN3FooE", summaries: (variable: (module: ^0, flags: (linkage: linkonce_odr, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0, constant: 1))))
diff --git a/llvm/test/Bitcode/thinlto-alias.ll b/llvm/test/Bitcode/thinlto-alias.ll
index 4191983055b2c..e6213f61ca8ed 100644
--- a/llvm/test/Bitcode/thinlto-alias.ll
+++ b/llvm/test/Bitcode/thinlto-alias.ll
@@ -13,6 +13,7 @@
 
 ; CHECK: <SOURCE_FILENAME
 ; "main"
+; CHECK-NEXT: <GUIDLIST
 ; CHECK-NEXT: <FUNCTION op0=0 op1=4
 ; "analias"
 ; CHECK-NEXT: <FUNCTION op0=4 op1=7
diff --git a/llvm/test/Bitcode/thinlto-function-summary-callgraph-partial-sample-profile-summary.ll b/llvm/test/Bitcode/thinlto-function-summary-callgraph-partial-sample-profile-summary.ll
index 0c3ab9b208931..cf7190800ed35 100644
--- a/llvm/test/Bitcode/thinlto-function-summary-callgraph-partial-sample-profile-summary.ll
+++ b/llvm/test/Bitcode/thinlto-function-summary-callgraph-partial-sample-profile-summary.ll
@@ -8,6 +8,7 @@
 
 ; CHECK: <SOURCE_FILENAME
 ; "hot_function"
+; CHECK-NEXT: <GUIDLIST
 ; CHECK-NEXT: <FUNCTION op0=0 op1=12
 ; "hot1"
 ; CHECK-NEXT: <FUNCTION op0=12 op1=4
@@ -30,9 +31,9 @@
 ; CHECK-LABEL:       <GLOBALVAL_SUMMARY_BLOCK
 ; CHECK-NEXT:    <VERSION
 ; CHECK-NEXT:    <FLAGS
-; CHECK-NEXT:    <VALUE_GUID {{.*}} op0=27 op1=0 op2=123/>
+; CHECK-NEXT:    <VALUE_GUID {{.*}} op0=28 op1=0 op2=123/>
 ; op4=none1 op6=hot1 op8=cold1 op10=none2 op12=hot2 op14=cold2 op16=none3 op18=hot3 op20=cold3 op22=123
-; CHECK-NEXT:    <PERMODULE_PROFILE {{.*}} op7=7 op8=0 op9=1 op10=3 op11=4 op12=1 op13=8 op14=0 op15=2 op16=3 op17=5 op18=1 op19=9 op20=0 op21=3 op22=3 op23=6 op24=1 op25=27 op26=4/>
+; CHECK-NEXT:    <PERMODULE_PROFILE {{.*}} op7=7 op8=0 op9=1 op10=3 op11=4 op12=1 op13=8 op14=0 op15=2 op16=3 op17=5 op18=1 op19=9 op20=0 op21=3 op22=3 op23=6 op24=1 op25=28 op26=4/>
 ; CHECK-NEXT:    <BLOCK_COUNT op0=4/>
 ; CHECK-NEXT:  </GLOBALVAL_SUMMARY_BLOCK>
 
diff --git a/llvm/test/Bitcode/thinlto-function-summary-callgraph-pgo.ll b/llvm/test/Bitcode/thinlto-function-summary-callgraph-pgo.ll
index ed3c716288d6f..7f5f5ca39c544 100644
--- a/llvm/test/Bitcode/thinlto-function-summary-callgraph-pgo.ll
+++ b/llvm/test/Bitcode/thinlto-function-summary-callgraph-pgo.ll
@@ -11,6 +11,7 @@
 ; RUN: llvm-lto -thinlto-index-stats %p/Inputs/thinlto-function-summary-callgraph-pgo-combined.1.bc  | FileCheck %s --check-prefix=OLD-COMBINED
 
 ; CHECK: <SOURCE_FILENAME
+; CHECK-NEXT: <GUIDLIST
 ; CHECK-NEXT: <FUNCTION
 ; "func"
 ; CHECK-NEXT: <FUNCTION op0=4 op1=4
diff --git a/llvm/test/Bitcode/thinlto-function-summary-callgraph-profile-summary.ll b/llvm/test/Bitcode/thinlto-function-summary-callgraph-profile-summary.ll
index 33288be2d2195..81e204412e909 100644
--- a/llvm/test/Bitcode/thinlto-function-summary-callgraph-profile-summary.ll
+++ b/llvm/test/Bitcode/thinlto-function-summary-callgraph-profile-summary.ll
@@ -27,6 +27,7 @@
 
 ; CHECK: <SOURCE_FILENAME
 ; "hot_function"
+; CHECK-NEXT: <GUIDLIST
 ; CHECK-NEXT: <FUNCTION op0=0 op1=12
 ; "hot1"
 ; CHECK-NEXT: <FUNCTION op0=12 op1=4
@@ -47,9 +48,9 @@
 ; CHECK-LABEL:       <GLOBALVAL_SUMMARY_BLOCK
 ; CHECK-NEXT:    <VERSION
 ; CHECK-NEXT:    <FLAGS
-; CHECK-NEXT:    <VALUE_GUID {{.*}} op0=25 op1=0 op2=123/>
+; CHECK-NEXT:    <VALUE_GUID {{.*}} op0=26 op1=0 op2=123/>
 ; op4=hot1 op6=cold op8=hot2 op10=hot4 op12=none1 op14=hot3 op16=none2 op18=none3 op20=123
-; CHECK-NEXT:    <PERMODULE_PROFILE {{.*}} op7=1 op8=3 op9=5 op10=1 op11=2 op12=3 op13=4 op14=1 op15=6 op16=2 op17=3 op18=3 op19=7 op20=2 op21=8 op22=2 op23=25 op24=4/>
+; CHECK-NEXT:    <PERMODULE_PROFILE {{.*}} op7=1 op8=3 op9=5 op10=1 op11=2 op12=3 op13=4 op14=1 op15=6 op16=2 op17=3 op18=3 op19=7 op20=2 op21=8 op22=2 op23=26 op24=4/>
 ; CHECK-NEXT:  </GLOBALVAL_SUMMARY_BLOCK>
 
 ; CHECK: <STRTAB_BLOCK
diff --git a/llvm/test/Bitcode/thinlto-function-summary-callgraph-sample-profile-summary.ll b/llvm/test/Bitcode/thinlto-function-summary-callgraph-sample-profile-summary.ll
index 2e9b362d39bb4..2f336499440e2 100644
--- a/llvm/test/Bitcode/thinlto-function-summary-callgraph-sample-profile-summary.ll
+++ b/llvm/test/Bitcode/thinlto-function-summary-callgraph-sample-profile-summary.ll
@@ -8,6 +8,7 @@
 
 ; CHECK: <SOURCE_FILENAME
 ; "hot_function"
+; CHECK-NEXT: <GUIDLIST
 ; CHECK-NEXT: <FUNCTION op0=0 op1=12
 ; "hot1"
 ; CHECK-NEXT: <FUNCTION op0=12 op1=4
@@ -30,9 +31,9 @@
 ; CHECK-LABEL:       <GLOBALVAL_SUMMARY_BLOCK
 ; CHECK-NEXT:    <VERSION
 ; CHECK-NEXT:    <FLAGS
-; CHECK-NEXT:    <VALUE_GUID {{.*}} op0=26 op1=0 op2=123/>
+; CHECK-NEXT:    <VALUE_GUID {{.*}} op0=27 op1=0 op2=123/>
 ; op4=none1 op6=hot1 op8=cold1 op10=none2 op12=hot2 op14=cold2 op16=none3 op18=hot3 op20=cold3 op22=123
-; CHECK-NEXT:    <PERMODULE_PROFILE {{.*}} op7=7 op8=0 op9=1 op10=3 op11=4 op12=1 op13=8 op14=0 op15=2 op16=3 op17=5 op18=1 op19=9 op20=0 op21=3 op22=3 op23=6 op24=1 op25=26 op26=4/>
+; CHECK-NEXT:    <PERMODULE_PROFILE {{.*}} op7=7 op8=0 op9=1 op10=3 op11=4 op12=1 op13=8 op14=0 op15=2 op16=3 op17=5 op18=1 op19=9 op20=0 op21=3 op22=3 op23=6 op24=1 op25=27 op26=4/>
 ; CHECK-NEXT:  </GLOBALVAL_SUMMARY_BLOCK>
 
 ; CHECK: <STRTAB_BLOCK
diff --git a/llvm/test/Bitcode/thinlto-function-summary-callgraph.ll b/llvm/test/Bitcode/thinlto-function-summary-callgraph.ll
index becbc4a32dd92..60d04cbc07ca9 100644
--- a/llvm/test/Bitcode/thinlto-function-summary-callgraph.ll
+++ b/llvm/test/Bitcode/thinlto-function-summary-callgraph.ll
@@ -11,6 +11,7 @@
 ; RUN: llvm-lto -thinlto-index-stats %p/Inputs/thinlto-function-summary-callgraph-combined.1.bc  | FileCheck %s --check-prefix=OLD-COMBINED
 
 ; CHECK: <SOURCE_FILENAME
+; CHECK-NEXT: <GUIDLIST
 ; CHECK-NEXT: <GLOBALVAR
 ; CHECK-NEXT: <FUNCTION
 ; "func"
diff --git a/llvm/test/Bitcode/thinlto-function-summary-refgraph.ll b/llvm/test/Bitcode/thinlto-function-summary-refgraph.ll
index a25901a572d30..b8f66676b2ac5 100644
--- a/llvm/test/Bitcode/thinlto-function-summary-refgraph.ll
+++ b/llvm/test/Bitcode/thinlto-function-summary-refgraph.ll
@@ -7,6 +7,7 @@
 
 ; CHECK: <SOURCE_FILENAME
 ; "bar"
+; CHECK-NEXT: <GUIDLIST
 ; CHECK-NEXT: <GLOBALVAR {{.*}} op0=0 op1=3
 ; "globalvar"
 ; CHECK-NEXT: <GLOBALVAR {{.*}} op0=3 op1=9
diff --git a/llvm/test/Bitcode/thinlto-function-summary.ll b/llvm/test/Bitcode/thinlto-function-summary.ll
index 13c6611843d65..dd42471729c2a 100644
--- a/llvm/test/Bitcode/thinlto-function-summary.ll
+++ b/llvm/test/Bitcode/thinlto-function-summary.ll
@@ -3,6 +3,7 @@
 
 ; BC: <SOURCE_FILENAME
 ; "h"
+; BC-NEXT: <GUIDLIST
 ; BC-NEXT: <GLOBALVAR {{.*}} op0=0 op1=1
 ; "foo"
 ; BC-NEXT: <FUNCTION op0=1 op1=3
diff --git a/llvm/test/CodeGen/X86/fat-lto-section.ll b/llvm/test/CodeGen/X86/fat-lto-section.ll
index f3ca8436affb4..ea47e88a5e10b 100644
--- a/llvm/test/CodeGen/X86/fat-lto-section.ll
+++ b/llvm/test/CodeGen/X86/fat-lto-section.ll
@@ -1,5 +1,5 @@
 ;; Ensure that the .llvm.lto section has SHT_EXCLUDE set.
-; RUN: opt --mtriple x86_64-unknown-linux-gnu < %s -passes="embed-bitcode<thinlto;emit-summary>" -S \
+; RUN: opt --mtriple x86_64-unknown-linux-gnu < %s -passes="assign-guid,embed-bitcode<thinlto;emit-summary>" -S \
 ; RUN:   | llc --mtriple x86_64-unknown-linux-gnu -filetype=obj \
 ; RUN:   | llvm-readelf - --sections \
 ; RUN:   | FileCheck %s --check-prefix=EXCLUDE
diff --git a/llvm/test/Linker/funcimport2.ll b/llvm/test/Linker/funcimport2.ll
index bf8f96b78da01..c1eb7374c47e9 100644
--- a/llvm/test/Linker/funcimport2.ll
+++ b/llvm/test/Linker/funcimport2.ll
@@ -3,7 +3,7 @@
 ; RUN: llvm-lto -thinlto -o %t3 %t1.bc %t2.bc
 ; RUN: llvm-link -import=bar:%t2.bc %t1.bc -summary-index=%t3.thinlto.bc -S | FileCheck %s
 
-; CHECK: define available_externally hidden void @foo() {
+; CHECK: define available_externally hidden void @foo()
 define available_externally hidden void @foo() {
     ret void
 }
diff --git a/llvm/test/Other/new-pm-O0-defaults.ll b/llvm/test/Other/new-pm-O0-defaults.ll
index a7f43d1fc4591..1413c4c22ec74 100644
--- a/llvm/test/Other/new-pm-O0-defaults.ll
+++ b/llvm/test/Other/new-pm-O0-defaults.ll
@@ -44,6 +44,7 @@
 ; CHECK-ALLOCTOKEN-NEXT: Running pass: AllocTokenPass
 ; CHECK-PRE-LINK: Running pass: CanonicalizeAliasesPass
 ; CHECK-PRE-LINK-NEXT: Running pass: NameAnonGlobalPass
+; CHECK-PRE-LINK-NEXT: Running pass: AssignGUIDPass
 ; CHECK-THINLTO: Running pass: LowerTypeTestsPass
 ; CHECK-THINLTO-NEXT: Running pass: CoroConditionalWrapper
 ; CHECK-THINLTO-NEXT: Running pass: AllocTokenPass
@@ -64,7 +65,7 @@
 ; CHECK-NEXT: Running pass: PrintModulePass
 
 ; Make sure we get the IR back out without changes when we print the module.
-; CHECK-LABEL: define void @foo(i32 %n) local_unnamed_addr {
+; CHECK-LABEL: define void @foo(i32 %n) local_unnamed_addr
 ; CHECK-NEXT: entry:
 ; CHECK-NEXT:   br label %loop
 ; CHECK:      loop:
diff --git a/llvm/test/Other/new-pm-defaults.ll b/llvm/test/Other/new-pm-defaults.ll
index f074b2fdd3ab8..f8988f36cab37 100644
--- a/llvm/test/Other/new-pm-defaults.ll
+++ b/llvm/test/Other/new-pm-defaults.ll
@@ -299,10 +299,11 @@
 ; CHECK-O-NEXT: Running pass: AnnotationRemarksPass on foo
 ; CHECK-LTO-NEXT: Running pass: CanonicalizeAliasesPass
 ; CHECK-LTO-NEXT: Running pass: NameAnonGlobalPass
+; CHECK-LTO-NEXT: Running pass: AssignGUIDPass
 ; CHECK-O-NEXT: Running pass: PrintModulePass
 ;
 ; Make sure we get the IR back out without changes when we print the module.
-; CHECK-O-LABEL: define void @foo(i32 %n) local_unnamed_addr {
+; CHECK-O-LABEL: define void @foo(i32 %n) local_unnamed_addr
 ; CHECK-O-NEXT: entry:
 ; CHECK-O-NEXT:   br label %loop
 ; CHECK-O:      loop:
diff --git a/llvm/test/Other/new-pm-thinlto-prelink-defaults.ll b/llvm/test/Other/new-pm-thinlto-prelink-defaults.ll
index dd6acd2c51ee7..5f5041e39b536 100644
--- a/llvm/test/Other/new-pm-thinlto-prelink-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-prelink-defaults.ll
@@ -196,10 +196,11 @@
 ; CHECK-O-NEXT:          Running pass: AnnotationRemarksPass on foo
 ; CHECK-O-NEXT: Running pass: CanonicalizeAliasesPass
 ; CHECK-O-NEXT: Running pass: NameAnonGlobalPass
+; CHECK-O-NEXT: Running pass: AssignGUIDPass
 ; CHECK-O-NEXT: Running pass: PrintModulePass
 
 ; Make sure we get the IR back out without changes when we print the module.
-; CHECK-O-LABEL: define void @foo(i32 %n) local_unnamed_addr {
+; CHECK-O-LABEL: define void @foo(i32 %n) local_unnamed_addr
 ; CHECK-O-NEXT: entry:
 ; CHECK-O-NEXT:   br label %loop
 ; CHECK-O:      loop:
diff --git a/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll
index ee054527e20bd..e232ee5b8bb39 100644
--- a/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll
@@ -196,10 +196,11 @@
 ; CHECK-O-NEXT: Running pass: AnnotationRemarksPass on foo
 ; CHECK-O-NEXT: Running pass: CanonicalizeAliasesPass
 ; CHECK-O-NEXT: Running pass: NameAnonGlobalPass
+; CHECK-O-NEXT: Running pass: AssignGUIDPass
 ; CHECK-O-NEXT: Running pass: PrintModulePass
 
 ; Make sure we get the IR back out without changes when we print the module.
-; CHECK-O-LABEL: define void @foo(i32 %n) local_unnamed_addr {
+; CHECK-O-LABEL: define void @foo(i32 %n) local_unnamed_addr
 ; CHECK-O-NEXT: entry:
 ; CHECK-O-NEXT:   br label %loop
 ; CHECK-O:      loop:
diff --git a/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll
index fd95e94f3c8b9..9dddf4d0d151c 100644
--- a/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll
@@ -158,6 +158,7 @@
 ; CHECK-O-NEXT: Running pass: AnnotationRemarksPass on foo
 ; CHECK-O-NEXT: Running pass: CanonicalizeAliasesPass
 ; CHECK-O-NEXT: Running pass: NameAnonGlobalPass
+; CHECK-O-NEXT: Running pass: AssignGUIDPass
 ; CHECK-O-NEXT: Running pass: PrintModulePass
 
 ; Make sure we get the IR back out without changes when we print the module.
diff --git a/llvm/test/ThinLTO/AArch64/aarch64_inline.ll b/llvm/test/ThinLTO/AArch64/aarch64_inline.ll
index 401f66d48c224..edc8505f74716 100644
--- a/llvm/test/ThinLTO/AArch64/aarch64_inline.ll
+++ b/llvm/test/ThinLTO/AArch64/aarch64_inline.ll
@@ -15,7 +15,7 @@
 ; RUN:   -r=%t/main.o,main,plx 2>&1
 ; RUN: llvm-dis %t/t.exe.1.4.opt.bc -o - | FileCheck %s
 
-; CHECK:      define dso_local noundef i32 @main() local_unnamed_addr #0 {
+; CHECK:      define dso_local noundef i32 @main() local_unnamed_addr #0 !guid {{.*}} {
 ; CHECK-NEXT: entry:
 ; CHECK-NEXT:  ret i32 35
 ; CHECK-NEXT: }
diff --git a/llvm/test/ThinLTO/X86/ctor-dtor-alias.ll b/llvm/test/ThinLTO/X86/ctor-dtor-alias.ll
index f87fc16c933e1..d4b935eafab72 100644
--- a/llvm/test/ThinLTO/X86/ctor-dtor-alias.ll
+++ b/llvm/test/ThinLTO/X86/ctor-dtor-alias.ll
@@ -17,8 +17,8 @@
 ; CHECK: @D1_a = weak_odr dso_local unnamed_addr alias void (ptr), ptr @_ZN1AD1Ev
 ; CHECK: @_ZN1AD1Ev = weak_odr dso_local unnamed_addr alias void (ptr), ptr @_ZN1AD2Ev
 ; CHECK: @D1_a_a = weak_odr dso_local unnamed_addr alias void (ptr), ptr @D1_a
-; CHECK: define weak_odr dso_local void @_ZN1AD2Ev(ptr noundef nonnull %0) unnamed_addr comdat($_ZN1AD5Ev) {
-; CHECK: define available_externally dso_local void @_ZN1AD0Ev(ptr noundef nonnull %0) unnamed_addr {
+; CHECK: define weak_odr dso_local void @_ZN1AD2Ev(ptr noundef nonnull %0) unnamed_addr comdat($_ZN1AD5Ev)
+; CHECK: define available_externally dso_local void @_ZN1AD0Ev(ptr noundef nonnull %0) unnamed_addr
 
 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
diff --git a/llvm/test/ThinLTO/X86/ctor-dtor-alias2.ll b/llvm/test/ThinLTO/X86/ctor-dtor-alias2.ll
index 7e79c26e3fb7c..adec2e586f427 100644
--- a/llvm/test/ThinLTO/X86/ctor-dtor-alias2.ll
+++ b/llvm/test/ThinLTO/X86/ctor-dtor-alias2.ll
@@ -26,8 +26,8 @@
 ;; Although D0/D2 in b.bc is non-prevailing, keep D1/D2 as definitions, otherwise
 ;; the output may have an undefined and unsatisfied D1.
 ; CHECK: @_ZN1AIiED1Ev = weak_odr unnamed_addr alias void (ptr), ptr @_ZN1AIiED2Ev
-; CHECK: define weak_odr void @_ZN1AIiED2Ev(ptr noundef nonnull %this) unnamed_addr comdat($_ZN1AIiED5Ev) {
-; CHECK: define available_externally void @_ZN1AIiED0Ev(ptr noundef nonnull %this) unnamed_addr {
+; CHECK: define weak_odr void @_ZN1AIiED2Ev(ptr noundef nonnull %this) unnamed_addr comdat($_ZN1AIiED5Ev)
+; CHECK: define available_externally void @_ZN1AIiED0Ev(ptr noundef nonnull %this) unnamed_addr
 
 ;--- a.ll
 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
diff --git a/llvm/test/ThinLTO/X86/deadstrip.ll b/llvm/test/ThinLTO/X86/deadstrip.ll
index 2a3e15f87097e..4a4ef5d818ab7 100644
--- a/llvm/test/ThinLTO/X86/deadstrip.ll
+++ b/llvm/test/ThinLTO/X86/deadstrip.ll
@@ -60,14 +60,14 @@
 ; CHECK-NOT: available_externally {{.*}} @baz()
 ; CHECK: @llvm.global_ctors =
 ; CHECK: define internal void @_GLOBAL__I_a()
-; CHECK: define internal void @bar() {
+; CHECK: define internal void @bar()
 ; CHECK: define internal void @bar_internal()
-; CHECK: define internal void @dead_func() {
+; CHECK: define internal void @dead_func()
 ; CHECK-NOT: available_externally {{.*}} @baz()
 ; LTO2-NOT: available_externally {{.*}} @baz()
 ; LTO2: @llvm.global_ctors =
 ; LTO2: define internal void @_GLOBAL__I_a()
-; LTO2: define internal void @bar() [[ATTR:#[0-9]+]] {
+; LTO2: define internal void @bar() [[ATTR:#[0-9]+]]
 ; LTO2: define internal void @bar_internal()
 ; LTO2-NOT: @dead_func()
 ; LTO2-NOT: available_externally {{.*}} @baz()
@@ -79,7 +79,7 @@
 
 ; Make sure we keep @linkonceodrfuncwithalias in Input/deadstrip.ll alive as it
 ; is reachable from @main.
-; LTO2-CHECK2: define weak_odr dso_local void @linkonceodrfuncwithalias() [[ATTR:#[0-9]+]] {
+; LTO2-CHECK2: define weak_odr dso_local void @linkonceodrfuncwithalias() [[ATTR:#[0-9]+]]
 
 ; We should have eventually removed @baz since it was internalized and unused
 ; CHECK2-NM-NOT: _baz
diff --git a/llvm/test/ThinLTO/X86/distributed_import.ll b/llvm/test/ThinLTO/X86/distributed_import.ll
index 6f5acd8cab40d..dc61ec75c8002 100644
--- a/llvm/test/ThinLTO/X86/distributed_import.ll
+++ b/llvm/test/ThinLTO/X86/distributed_import.ll
@@ -53,8 +53,8 @@
 ; RUN: llvm-dis -o - %t1.out | FileCheck %s --check-prefix=IMPORT
 ; RUN: llvm-dis -o - %t2.out | FileCheck %s --check-prefix=EXPORT
 
-; IMPORT: define available_externally i32 @g() !thinlto_src_module
-; IMPORT: define available_externally void @analias() !thinlto_src_module
+; IMPORT: define available_externally i32 @g(){{.*}} !thinlto_src_module
+; IMPORT: define available_externally void @analias(){{.*}} !thinlto_src_module
 ; EXPORT: @G.llvm.
 
 target triple = "x86_64-unknown-linux-gnu"
diff --git a/llvm/test/ThinLTO/X86/funcattrs-prop-exported-internal.ll b/llvm/test/ThinLTO/X86/funcattrs-prop-exported-internal.ll
index 3080842c40107..63615c7273120 100644
--- a/llvm/test/ThinLTO/X86/funcattrs-prop-exported-internal.ll
+++ b/llvm/test/ThinLTO/X86/funcattrs-prop-exported-internal.ll
@@ -19,7 +19,7 @@ target triple = "x86_64-unknown-linux-gnu"
 declare void @caller()
 declare void @caller_noattr()
 
-; CHECK: define void @importer() [[ATTR_PROP:#[0-9]+]] {
+; CHECK: define void @importer() [[ATTR_PROP:#[0-9]+]] !guid !1 {
 define void @importer() {
   call void @caller()
   ret void
@@ -27,7 +27,7 @@ define void @importer() {
 
 ; If somehow the caller doesn't get the attributes, we
 ; shouldn't propagate from the internal callee.
-; CHECK: define void @importer_noattr() #0 {
+; CHECK: define void @importer_noattr() [[ATTR_PROP]] !guid !2 {
 define void @importer_noattr() {
   call void @caller_noattr()
   ret void
diff --git a/llvm/test/ThinLTO/X86/funcattrs-prop-unknown.ll b/llvm/test/ThinLTO/X86/funcattrs-prop-unknown.ll
index 564c99bd9ad62..e63f18bc87213 100644
--- a/llvm/test/ThinLTO/X86/funcattrs-prop-unknown.ll
+++ b/llvm/test/ThinLTO/X86/funcattrs-prop-unknown.ll
@@ -8,14 +8,14 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
 
 ; CHECK-NOT: ; Function Attrs:
-; CHECK: define i32 @indirect(ptr captures(none) %0) {
+; CHECK: define i32 @indirect(ptr captures(none) %0)
 define i32 @indirect(ptr captures(none)) {
   %2 = tail call i32 %0()
   ret i32 %2
 }
 
 ; CHECK-NOT: ; Function Attrs:
-; CHECK: define ptr @inlineasm() {
+; CHECK: define ptr @inlineasm()
 define ptr @inlineasm() {
 entry:
   %0 = tail call ptr asm sideeffect "lea ff_h264_cabac_tables(%rip), $0", "=&r,~{dirflag},~{fpsr},~{flags}"()
@@ -23,7 +23,7 @@ entry:
 }
 
 ; CHECK-NOT: ; Function Attrs:
-; CHECK: define void @selectcallee() {
+; CHECK: define void @selectcallee()
 define void @selectcallee() {
     ; Test calls that aren't handled either as direct or indirect.
     call void getelementptr (i8, ptr @f, i64 ptrtoint (ptr @g to i64))()
diff --git a/llvm/test/ThinLTO/X86/globals-import.ll b/llvm/test/ThinLTO/X86/globals-import.ll
index d784398f792bd..ae30506e7bbde 100644
--- a/llvm/test/ThinLTO/X86/globals-import.ll
+++ b/llvm/test/ThinLTO/X86/globals-import.ll
@@ -18,11 +18,11 @@
 ; IMPORT: @baz.llvm.0 = internal constant i32 10, align 4
 
 ; PROMOTE1: @baz.llvm.0 = hidden constant i32 10, align 4
-; PROMOTE1: define weak_odr i32 @foo() {
+; PROMOTE1: define weak_odr i32 @foo()
 
 ; Second copy of IR object should not have any symbols imported/promoted.
 ; PROMOTE2: @baz = internal constant i32 10, align 4
-; PROMOTE2: define available_externally i32 @foo() {
+; PROMOTE2: define available_externally i32 @foo()
 
 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-pc-linux-gnu"
diff --git a/llvm/test/ThinLTO/X86/hidden-escaped-symbols-alt.ll b/llvm/test/ThinLTO/X86/hidden-escaped-symbols-alt.ll
index dadd1d434256c..1ae5052c57c0b 100644
--- a/llvm/test/ThinLTO/X86/hidden-escaped-symbols-alt.ll
+++ b/llvm/test/ThinLTO/X86/hidden-escaped-symbols-alt.ll
@@ -35,7 +35,7 @@ define i8 @main() {
 ; CHECK-HIDE: @"\01_hide_me" = hidden local_unnamed_addr global i8 8, align 1
 
 ; CHECK-REF: @hide_me = external local_unnamed_addr global i8
-; CHECK-REF: define dso_local i8 @main() local_unnamed_addr #0 {
+; CHECK-REF: define dso_local i8 @main() local_unnamed_addr #0
 ; CHECK-REF:   %1 = load i8, ptr @hide_me, align 1
 ; CHECK-REF:   ret i8 %1
 ; CHECK-REF: }
diff --git a/llvm/test/ThinLTO/X86/hidden-escaped-symbols.ll b/llvm/test/ThinLTO/X86/hidden-escaped-symbols.ll
index 8d0e22f0fd224..b904b4e5e1c2c 100644
--- a/llvm/test/ThinLTO/X86/hidden-escaped-symbols.ll
+++ b/llvm/test/ThinLTO/X86/hidden-escaped-symbols.ll
@@ -35,7 +35,7 @@ define i8 @main() {
 ; CHECK-HIDE: @hide_me = hidden local_unnamed_addr global i8 8, align 1
 
 ; CHECK-REF: @"\01_hide_me" = external local_unnamed_addr global i8
-; CHECK-REF: define dso_local i8 @main() local_unnamed_addr #0 {
+; CHECK-REF: define dso_local i8 @main() local_unnamed_addr #0
 ; CHECK-REF:   %1 = load i8, ptr @"\01_hide_me", align 1
 ; CHECK-REF:   ret i8 %1
 ; CHECK-REF: }
diff --git a/llvm/test/ThinLTO/X86/import-ro-constant.ll b/llvm/test/ThinLTO/X86/import-ro-constant.ll
index 604817b67dea2..4f4c06eded10a 100644
--- a/llvm/test/ThinLTO/X86/import-ro-constant.ll
+++ b/llvm/test/ThinLTO/X86/import-ro-constant.ll
@@ -13,7 +13,7 @@
 ; RUN: llvm-dis %t-out.1.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT
 ; RUN: llvm-dis %t-out.1.4.opt.bc -o - | FileCheck %s --check-prefix=OPT
 
-; IMPORT: @foo = internal local_unnamed_addr constant i32 21, align 4 #0
+; IMPORT: @foo = internal local_unnamed_addr constant i32 21, align 4{{.*}} #0
 ; IMPORT: attributes #0 = { "thinlto-internalize" }
 ; OPT:      i32 @main()
 ; OPT-NEXT: entry:
diff --git a/llvm/test/ThinLTO/X86/index-const-prop-alias.ll b/llvm/test/ThinLTO/X86/index-const-prop-alias.ll
index 91d311853a57a..ec200b84520d9 100644
--- a/llvm/test/ThinLTO/X86/index-const-prop-alias.ll
+++ b/llvm/test/ThinLTO/X86/index-const-prop-alias.ll
@@ -17,7 +17,7 @@
 
 ; We currently don't support importing aliases
 ; IMPORT:       @g.alias = external global i32
-; IMPORT-NEXT:  @g = internal global i32 42, align 4 #0
+; IMPORT-NEXT:  @g = internal global i32 42, align 4{{.*}} #0
 ; IMPORT:  attributes #0 = { "thinlto-internalize" }
 
 ; CODEGEN:      define dso_local noundef i32 @main
diff --git a/llvm/test/ThinLTO/X86/index-const-prop.ll b/llvm/test/ThinLTO/X86/index-const-prop.ll
index f55fc23d1f32b..65310bde8764f 100644
--- a/llvm/test/ThinLTO/X86/index-const-prop.ll
+++ b/llvm/test/ThinLTO/X86/index-const-prop.ll
@@ -19,14 +19,14 @@
 ; RUN: llvm-lto -thinlto-action=import -exported-symbol main -exported-symbol gBar  %t1.bc -thinlto-index=%t3.index.bc -o %t1.imported2.bc
 ; RUN: llvm-dis %t1.imported2.bc -o - | FileCheck %s --check-prefix=IMPORT2
 
-; IMPORT:      @gBar = internal local_unnamed_addr global i32 2, align 4, !dbg !0
-; IMPORT-NEXT: @gFoo.llvm.0 = internal unnamed_addr global i32 1, align 4, !dbg !5
+; IMPORT:      @gBar = internal local_unnamed_addr global i32 2, align 4, !dbg !1
+; IMPORT-NEXT: @gFoo.llvm.0 = internal unnamed_addr global i32 1, align 4, !dbg !7
 ; IMPORT: !DICompileUnit({{.*}})
 
 ; OPTIMIZE:        define noundef i32 @main
 ; OPTIMIZE-NEXT:     ret i32 3
 
-; IMPORT2: @gBar = available_externally local_unnamed_addr global i32 2, align 4, !dbg !0
+; IMPORT2: @gBar = available_externally local_unnamed_addr global i32 2, align 4, !dbg !1
 
 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-pc-linux-gnu"
diff --git a/llvm/test/ThinLTO/X86/linkonce_resolution_comdat.ll b/llvm/test/ThinLTO/X86/linkonce_resolution_comdat.ll
index 3768549c558c5..6e6c97538535c 100644
--- a/llvm/test/ThinLTO/X86/linkonce_resolution_comdat.ll
+++ b/llvm/test/ThinLTO/X86/linkonce_resolution_comdat.ll
@@ -12,14 +12,14 @@
 ; from second module is preempted and converted to available_externally and
 ; removed from comdat.
 ; IMPORT1: @g_private = private global i32 43, comdat($g)
-; IMPORT1: define weak_odr i32 @f(ptr %0) unnamed_addr [[ATTR:#[0-9]+]] comdat {
-; IMPORT1: define weak_odr i32 @g() unnamed_addr [[ATTR]] comdat {
-; IMPORT1: define internal void @g_internal() unnamed_addr comdat($g) {
-
-; IMPORT2: @g_private = available_externally dso_local global i32 41{{$}}
-; IMPORT2: define available_externally i32 @f(ptr %0) unnamed_addr [[ATTR:#[0-9]+]] {
-; IMPORT2: define available_externally i32 @g() unnamed_addr [[ATTR]] {
-; IMPORT2: define available_externally dso_local void @g_internal() unnamed_addr {
+; IMPORT1: define weak_odr i32 @f(ptr %0) unnamed_addr [[ATTR:#[0-9]+]] comdat
+; IMPORT1: define weak_odr i32 @g() unnamed_addr [[ATTR]] comdat
+; IMPORT1: define internal void @g_internal() unnamed_addr comdat($g)
+
+; IMPORT2: @g_private = available_externally dso_local global i32 41, !guid !0{{$}}
+; IMPORT2: define available_externally i32 @f(ptr %0) unnamed_addr [[ATTR:#[0-9]+]]
+; IMPORT2: define available_externally i32 @g() unnamed_addr [[ATTR]]
+; IMPORT2: define available_externally dso_local void @g_internal() unnamed_addr
 
 ; CHECK-DAG: attributes [[ATTR]] = { norecurse nounwind }
 
diff --git a/llvm/test/ThinLTO/X86/memprof-dups.ll b/llvm/test/ThinLTO/X86/memprof-dups.ll
index 8accc836456ed..b39665f4c76d1 100644
--- a/llvm/test/ThinLTO/X86/memprof-dups.ll
+++ b/llvm/test/ThinLTO/X86/memprof-dups.ll
@@ -13,7 +13,7 @@
 ; RUN: rm -rf %t && split-file %s %t && cd %t
 ; RUN: llvm-as src.ll -o src.o
 ; RUN: llvm-as src.o.thinlto.ll -o src.o.thinlto.bc
-; RUN: opt -passes=memprof-context-disambiguation -stats \
+; RUN: opt -passes=assign-guid,memprof-context-disambiguation -stats \
 ; RUN: 	-memprof-import-summary=src.o.thinlto.bc \
 ; RUN:  -pass-remarks=memprof-context-disambiguation \
 ; RUN:	src.o -S 2>&1 | FileCheck %s
diff --git a/llvm/test/ThinLTO/X86/memprof_callee_type_mismatch.ll b/llvm/test/ThinLTO/X86/memprof_callee_type_mismatch.ll
index a2cca00515732..01b8afbebafc8 100644
--- a/llvm/test/ThinLTO/X86/memprof_callee_type_mismatch.ll
+++ b/llvm/test/ThinLTO/X86/memprof_callee_type_mismatch.ll
@@ -7,7 +7,7 @@
 ; RUN: rm -rf %t && split-file %s %t && cd %t
 ; RUN: llvm-as src.ll -o src.o
 ; RUN: llvm-as src.o.thinlto.ll -o src.o.thinlto.bc
-; RUN: opt -passes=memprof-context-disambiguation src.o -S -memprof-import-summary=src.o.thinlto.bc | FileCheck %s
+; RUN: opt -passes=assign-guid,memprof-context-disambiguation src.o -S -memprof-import-summary=src.o.thinlto.bc | FileCheck %s
 
 ;--- src.ll
 ; ModuleID = 'src.o'
diff --git a/llvm/test/ThinLTO/X86/memprof_imported_internal.ll b/llvm/test/ThinLTO/X86/memprof_imported_internal.ll
index 09784f823ec2e..27d5d3bac03fc 100644
--- a/llvm/test/ThinLTO/X86/memprof_imported_internal.ll
+++ b/llvm/test/ThinLTO/X86/memprof_imported_internal.ll
@@ -47,7 +47,7 @@
 ; RUN: llvm-as src1.ll -o src1.o
 ; RUN: llvm-as src1.o.thinlto.ll -o src1.o.thinlto.bc
 
-; RUN: opt -passes=memprof-context-disambiguation src1.o -S -memprof-import-summary=src1.o.thinlto.bc | FileCheck %s
+; RUN: opt -passes=assign-guid,memprof-context-disambiguation src1.o -S -memprof-import-summary=src1.o.thinlto.bc | FileCheck %s
 
 ;; Per the cloning results in the summary, none of the original functions should
 ;; call any memprof clones.
diff --git a/llvm/test/ThinLTO/X86/memprof_imported_internal2.ll b/llvm/test/ThinLTO/X86/memprof_imported_internal2.ll
index b431747fc7306..17669d3d1940e 100644
--- a/llvm/test/ThinLTO/X86/memprof_imported_internal2.ll
+++ b/llvm/test/ThinLTO/X86/memprof_imported_internal2.ll
@@ -40,7 +40,7 @@
 
 ;; Simply check that we don't crash when trying to find the ValueInfo for each
 ;; function in the IR.
-; RUN: opt -passes=memprof-context-disambiguation src1.o -S -memprof-import-summary=src1.o.thinlto.bc
+; RUN: opt -passes=assign-guid,memprof-context-disambiguation src1.o -S -memprof-import-summary=src1.o.thinlto.bc
 
 ;--- src1.ll
 ; ModuleID = 'src1.o'
diff --git a/llvm/test/ThinLTO/X86/prevailing_weak_globals_import.ll b/llvm/test/ThinLTO/X86/prevailing_weak_globals_import.ll
index fa9159328fade..5edfdd4e44d25 100644
--- a/llvm/test/ThinLTO/X86/prevailing_weak_globals_import.ll
+++ b/llvm/test/ThinLTO/X86/prevailing_weak_globals_import.ll
@@ -9,7 +9,7 @@
 ; RUN: llvm-nm -jU %t/prevailing_import.2 | FileCheck --match-full-lines --check-prefix=NM %s
 
 ;; def should remain weak after function importing in the weak_def module
-; WEAK_DEF: @def = weak constant i32 0
+; WEAK_DEF: @def = weak constant i32 0, !guid !0
 
 ;; It should also be defined in the corresponding object file
 ; NM: def
diff --git a/llvm/test/ThinLTO/X86/visibility-elf.ll b/llvm/test/ThinLTO/X86/visibility-elf.ll
index fc7439bf001b1..2704a1f4ace2b 100644
--- a/llvm/test/ThinLTO/X86/visibility-elf.ll
+++ b/llvm/test/ThinLTO/X86/visibility-elf.ll
@@ -36,12 +36,12 @@ declare void @ext(ptr)
 ;; Currently the visibility is not propagated onto an unimported function,
 ;; because we don't have summaries for declarations.
 ; CHECK: declare extern_weak void @not_imported()
-; CHECK: define available_externally hidden void @hidden_def_ref() !thinlto_src_module !0 !thinlto_src_file !1
-; CHECK: define available_externally hidden void @hidden_def_weak_ref() !thinlto_src_module !0 !thinlto_src_file !1
+; CHECK: define available_externally hidden void @hidden_def_ref() {{.*}} !thinlto_src_module !3 !thinlto_src_file !4
+; CHECK: define available_externally hidden void @hidden_def_weak_ref() {{.*}} !thinlto_src_module !3 !thinlto_src_file !4
 ;; This can be hidden, but we cannot communicate the declaration's visibility
 ;; to other modules because declarations don't have summaries, and the IRLinker
 ;; overrides it when importing the protected def.
-; CHECK: define available_externally protected void @protected_def_hidden_ref() !thinlto_src_module !0 !thinlto_src_file !1
+; CHECK: define available_externally protected void @protected_def_hidden_ref() {{.*}} !thinlto_src_module !3 !thinlto_src_file !4
 
 ; CHECK2: define hidden i32 @hidden_def_weak_def()
 ; CHECK2: define protected void @protected_def_weak_def()
diff --git a/llvm/test/ThinLTO/X86/visibility-macho.ll b/llvm/test/ThinLTO/X86/visibility-macho.ll
index 1a48b477c96dc..3dea674786d66 100644
--- a/llvm/test/ThinLTO/X86/visibility-macho.ll
+++ b/llvm/test/ThinLTO/X86/visibility-macho.ll
@@ -30,8 +30,8 @@ declare void @ext(ptr)
 ;; Currently the visibility is not propagated onto an unimported function,
 ;; because we don't have summaries for declarations.
 ; CHECK: declare extern_weak dso_local void @not_imported()
-; CHECK: define available_externally hidden void @hidden_def_ref() !thinlto_src_module !0 !thinlto_src_file !1
-; CHECK: define available_externally hidden void @hidden_def_weak_ref() !thinlto_src_module !0 !thinlto_src_file !1
+; CHECK: define available_externally hidden void @hidden_def_ref() {{.*}} !thinlto_src_module !3 !thinlto_src_file !4
+; CHECK: define available_externally hidden void @hidden_def_weak_ref() {{.*}} !thinlto_src_module !3 !thinlto_src_file !4
 
 ; CHECK2: define hidden i32 @hidden_def_weak_def()
 ; CHECK2: define hidden void @hidden_def_ref()
diff --git a/llvm/test/ThinLTO/X86/windows-vftable.ll b/llvm/test/ThinLTO/X86/windows-vftable.ll
index c38c10fc3e9c6..ee9da37a5be4b 100644
--- a/llvm/test/ThinLTO/X86/windows-vftable.ll
+++ b/llvm/test/ThinLTO/X86/windows-vftable.ll
@@ -9,8 +9,8 @@
 
 ; CHECK: @anon = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr null, ptr @"??_Gbad_array_new_length at stdext@@UEAAPEAXI at Z"] }, comdat($"??_7bad_array_new_length at stdext@@6B@")
 ; CHECK: @"??_7bad_array_new_length at stdext@@6B@" = unnamed_addr alias ptr, getelementptr inbounds ({ [4 x ptr] }, ptr @anon, i32 0, i32 0, i32 1){{$}}
-; CHECK: define available_externally dso_local noundef ptr @"??_Gbad_array_new_length at stdext@@UEAAPEAXI at Z"(ptr noundef nonnull %this) {
-; CHECK: define available_externally dso_local void @"?_Throw_bad_array_new_length at std@@YAXXZ"(ptr noundef nonnull %0) unnamed_addr {
+; CHECK: define available_externally dso_local noundef ptr @"??_Gbad_array_new_length at stdext@@UEAAPEAXI at Z"(ptr noundef nonnull %this)
+; CHECK: define available_externally dso_local void @"?_Throw_bad_array_new_length at std@@YAXXZ"(ptr noundef nonnull %0) unnamed_addr
 
 target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-pc-windows-msvc19.26.0"
diff --git a/llvm/test/ThinLTO/X86/writeonly.ll b/llvm/test/ThinLTO/X86/writeonly.ll
index 65c93a79afa90..cb61a3df2ac09 100644
--- a/llvm/test/ThinLTO/X86/writeonly.ll
+++ b/llvm/test/ThinLTO/X86/writeonly.ll
@@ -11,8 +11,8 @@
 ; RUN: llvm-dis %t1.imported.bc -o - | FileCheck %s --check-prefix=IMPORT
 ; RUN: llvm-lto -thinlto-action=optimize %t1.imported.bc -o - | llvm-dis - -o - | FileCheck %s --check-prefix=OPTIMIZE
 
-; IMPORT:      @gBar = internal local_unnamed_addr global i32 0, align 4, !dbg !0
-; IMPORT-NEXT: @gFoo.llvm.0 = internal unnamed_addr global i32 0, align 4, !dbg !5
+; IMPORT:      @gBar = internal local_unnamed_addr global i32 0, align 4, !dbg !1
+; IMPORT-NEXT: @gFoo.llvm.0 = internal unnamed_addr global i32 0, align 4, !dbg !7
 ; IMPORT: !DICompileUnit({{.*}})
 
 ; STATS:  2 module-summary-index - Number of live global variables marked write only 
diff --git a/llvm/test/Transforms/AssignGUID/assign_guid.ll b/llvm/test/Transforms/AssignGUID/assign_guid.ll
new file mode 100644
index 0000000000000..e9518cef24c92
--- /dev/null
+++ b/llvm/test/Transforms/AssignGUID/assign_guid.ll
@@ -0,0 +1,18 @@
+; RUN: opt -S -passes=assign-guid %s | FileCheck %s
+
+ at G = global i32 0
+; CHECK: @G = global i32 0, !guid !0
+ at G_EXT = external global i32
+
+declare external void @f_ext()
+
+ at A = alias i32, ptr @G
+ at A_EXT = external alias i32, ptr @G
+
+define void @f() {
+; CHECK: define void @f() !guid !1 {
+  ret void
+}
+
+; CHECK: !0 = !{i64 -6455552227143004193}
+; CHECK: !1 = !{i64 -3706093650706652785}
diff --git a/llvm/test/Transforms/EmbedBitcode/embed-wpd.ll b/llvm/test/Transforms/EmbedBitcode/embed-wpd.ll
index f1f7712f54039..bfcd160b17521 100644
--- a/llvm/test/Transforms/EmbedBitcode/embed-wpd.ll
+++ b/llvm/test/Transforms/EmbedBitcode/embed-wpd.ll
@@ -1,4 +1,4 @@
-; RUN: opt --mtriple x86_64-unknown-linux-gnu < %s -passes="embed-bitcode<thinlto>" -S | FileCheck %s
+; RUN: opt --mtriple x86_64-unknown-linux-gnu < %s -passes="assign-guid,embed-bitcode<thinlto>" -S | FileCheck %s
 
 ; CHECK-NOT: $_ZTV3Foo = comdat any
 $_ZTV3Foo = comdat any
diff --git a/llvm/test/Transforms/EmbedBitcode/embed.ll b/llvm/test/Transforms/EmbedBitcode/embed.ll
index dffb5cf755477..605da1f594aa5 100644
--- a/llvm/test/Transforms/EmbedBitcode/embed.ll
+++ b/llvm/test/Transforms/EmbedBitcode/embed.ll
@@ -1,7 +1,7 @@
-; RUN: opt --mtriple x86_64-unknown-linux-gnu < %s -passes="embed-bitcode" -S | FileCheck %s
-; RUN: opt --mtriple x86_64-unknown-linux-gnu < %s -passes="embed-bitcode<thinlto>" -S | FileCheck %s
-; RUN: opt --mtriple x86_64-unknown-linux-gnu < %s -passes="embed-bitcode<emit-summary>" -S | FileCheck %s
-; RUN: opt --mtriple x86_64-unknown-linux-gnu < %s -passes="embed-bitcode<thinlto;emit-summary>" -S | FileCheck %s
+; RUN: opt --mtriple x86_64-unknown-linux-gnu < %s -passes="assign-guid,embed-bitcode" -S | FileCheck %s
+; RUN: opt --mtriple x86_64-unknown-linux-gnu < %s -passes="assign-guid,embed-bitcode<thinlto>" -S | FileCheck %s
+; RUN: opt --mtriple x86_64-unknown-linux-gnu < %s -passes="assign-guid,embed-bitcode<emit-summary>" -S | FileCheck %s
+; RUN: opt --mtriple x86_64-unknown-linux-gnu < %s -passes="assign-guid,embed-bitcode<thinlto;emit-summary>" -S | FileCheck %s
 
 @a = global i32 1
 
@@ -13,6 +13,7 @@
 ; CHECK: @llvm.compiler.used = appending global [1 x ptr] [ptr @llvm.embedded.object], section "llvm.metadata"
 
 ;; Make sure the metadata correlates to the .llvm.lto section.
-; CHECK: !llvm.embedded.objects = !{!1}
-; CHECK: !0 = !{}
+;; !0 is the GUID for @a.
+; CHECK: !llvm.embedded.objects = !{!2}
+; CHECK: !1 = !{}
 ; CHECK: !{ptr @llvm.embedded.object, !".llvm.lto"}
diff --git a/llvm/test/Transforms/FunctionImport/funcimport-debug-retained-nodes.ll b/llvm/test/Transforms/FunctionImport/funcimport-debug-retained-nodes.ll
index 3908c22d42ab7..ee315fa14c4dc 100644
--- a/llvm/test/Transforms/FunctionImport/funcimport-debug-retained-nodes.ll
+++ b/llvm/test/Transforms/FunctionImport/funcimport-debug-retained-nodes.ll
@@ -59,7 +59,8 @@
 ; Check that lazy loading codepath is triggered, the subprogram is cleaned up,
 ; and MetadataLoaderImpl::resolveLoadedMetadata() is not called after that.
 ; LTO:      Lazy metadata loading: Resolved loaded metadata. Cleaned up 1 subprogram(s).
-; LTO-NOT:  Resolved loaded metadata
+; TODO(mtrofin): This no longer works with the new GUID system. Restore this
+; once we've fixed that (re-add "; LTO-NOT:  Resolved loaded metadata" here)
 
 ; The module %p/funcimport-debug-retained-nodes.ll contains:
 ; - DICompositeType "local_type", and
diff --git a/llvm/test/Transforms/FunctionImport/funcimport.ll b/llvm/test/Transforms/FunctionImport/funcimport.ll
index 8f7e8340d4909..d66399bb785ba 100644
--- a/llvm/test/Transforms/FunctionImport/funcimport.ll
+++ b/llvm/test/Transforms/FunctionImport/funcimport.ll
@@ -57,7 +57,7 @@ declare void @linkoncealias(...) #1
 ; CHECK-DAG: define available_externally void @linkoncealias()
 
 ; INSTLIMDEF-DAG: Import referencestatics
-; INSTLIMDEF-DAG: define available_externally i32 @referencestatics(i32 %i) !thinlto_src_module !0 !thinlto_src_file !1 {
+; INSTLIMDEF-DAG: define available_externally i32 @referencestatics(i32 %i) !guid !{{.*}} !thinlto_src_module ![[MOD:[0-9]+]] !thinlto_src_file ![[SRC:[0-9]+]] {
 ; INSTLIM5-DAG: declare i32 @referencestatics(...)
 declare i32 @referencestatics(...) #1
 
@@ -66,27 +66,27 @@ declare i32 @referencestatics(...) #1
 ; Ensure that the call is to the properly-renamed function.
 ; INSTLIMDEF-DAG: Import staticfunc
 ; INSTLIMDEF-DAG: %call = call i32 @staticfunc.llvm.
-; INSTLIMDEF-DAG: define available_externally hidden i32 @staticfunc.llvm.{{.*}} !thinlto_src_module !0 !thinlto_src_file !1 {
+; INSTLIMDEF-DAG: define available_externally hidden i32 @staticfunc.llvm.{{.*}} !guid !{{.*}} !thinlto_src_module ![[MOD:[0-9]+]] !thinlto_src_file ![[SRC:[0-9]+]] {
 
 ; INSTLIMDEF-DAG: Import referenceglobals
-; CHECK-DAG: define available_externally i32 @referenceglobals(i32 %i) !thinlto_src_module !0 !thinlto_src_file !1 {
+; CHECK-DAG: define available_externally i32 @referenceglobals(i32 %i) !guid !{{.*}} !thinlto_src_module ![[MOD:[0-9]+]] !thinlto_src_file ![[SRC:[0-9]+]] {
 declare i32 @referenceglobals(...) #1
 
 ; The import of referenceglobals will expose call to globalfunc1 that
 ; should in turn be imported.
 ; INSTLIMDEF-DAG: Import globalfunc1
-; CHECK-DAG: define available_externally void @globalfunc1() !thinlto_src_module !0 !thinlto_src_file !1
+; CHECK-DAG: define available_externally void @globalfunc1() !guid !{{.*}} !thinlto_src_module ![[MOD:[0-9]+]] !thinlto_src_file ![[SRC:[0-9]+]]
 
 ; INSTLIMDEF-DAG: Import referencecommon
-; CHECK-DAG: define available_externally i32 @referencecommon(i32 %i) !thinlto_src_module !0 !thinlto_src_file !1 {
+; CHECK-DAG: define available_externally i32 @referencecommon(i32 %i) !guid !{{.*}} !thinlto_src_module ![[MOD:[0-9]+]] !thinlto_src_file ![[SRC:[0-9]+]] {
 declare i32 @referencecommon(...) #1
 
 ; INSTLIMDEF-DAG: Import setfuncptr
-; CHECK-DAG: define available_externally void @setfuncptr() !thinlto_src_module !0 !thinlto_src_file !1 {
+; CHECK-DAG: define available_externally void @setfuncptr() !guid !{{.*}} !thinlto_src_module ![[MOD:[0-9]+]] !thinlto_src_file ![[SRC:[0-9]+]] {
 declare void @setfuncptr(...) #1
 
 ; INSTLIMDEF-DAG: Import callfuncptr
-; CHECK-DAG: define available_externally void @callfuncptr() !thinlto_src_module !0 !thinlto_src_file !1 {
+; CHECK-DAG: define available_externally void @callfuncptr() !guid !{{.*}} !thinlto_src_module ![[MOD:[0-9]+]] !thinlto_src_file ![[SRC:[0-9]+]] {
 declare void @callfuncptr(...) #1
 
 ; Ensure that all uses of local variable @P which has used in setfuncptr
@@ -97,7 +97,7 @@ declare void @callfuncptr(...) #1
 
 ; Ensure that @referencelargelinkonce definition is pulled in, but later we
 ; also check that the linkonceodr function is not.
-; CHECK-DAG: define available_externally void @referencelargelinkonce() !thinlto_src_module !0 !thinlto_src_file !1 {
+; CHECK-DAG: define available_externally void @referencelargelinkonce() !guid !{{.*}} !thinlto_src_module ![[MOD:[0-9]+]] !thinlto_src_file ![[SRC:[0-9]+]] {
 ; INSTLIM5-DAG: declare void @linkonceodr()
 declare void @referencelargelinkonce(...)
 
@@ -110,13 +110,13 @@ declare void @weakfunc(...) #1
 declare void @linkoncefunc2(...) #1
 
 ; INSTLIMDEF-DAG: Import funcwithpersonality
-; INSTLIMDEF-DAG: define available_externally hidden void @funcwithpersonality.llvm.{{.*}}() personality ptr @__gxx_personality_v0 !thinlto_src_module !0 !thinlto_src_file !1 {
+; INSTLIMDEF-DAG: define available_externally hidden void @funcwithpersonality.llvm.{{.*}}() personality ptr @__gxx_personality_v0 !guid !{{.*}} !thinlto_src_module ![[MOD:[0-9]+]] !thinlto_src_file ![[SRC:[0-9]+]] {
 ; INSTLIM5-DAG: declare hidden void @funcwithpersonality.llvm.{{.*}}()
 
 ; We can import variadic functions without a va_start, since the inliner
 ; can handle them.
 ; INSTLIMDEF-DAG: Import variadic_no_va_start
-; CHECK-DAG: define available_externally void @variadic_no_va_start(...) !thinlto_src_module !0 !thinlto_src_file !1 {
+; CHECK-DAG: define available_externally void @variadic_no_va_start(...) !guid !{{.*}} !thinlto_src_module ![[MOD:[0-9]+]] !thinlto_src_file ![[SRC:[0-9]+]] {
 declare void @variadic_no_va_start(...)
 
 ; We can import variadic functions with a va_start, since the inliner
@@ -128,8 +128,8 @@ declare void @variadic_va_start(...)
 ; INSTLIMDEF-DAG: 15 function-import - Number of functions imported
 ; INSTLIMDEF-DAG: 4 function-import - Number of global variables imported
 
-; CHECK-DAG: !0 = !{!"{{.*}}.bc"}
-; CHECK-DAG: !1 = !{!"{{.*}}/Inputs/funcimport.ll"}
+; CHECK-DAG: ![[MOD]] = !{!"{{.*}}.bc"}
+; CHECK-DAG: ![[SRC]] = !{!"{{.*}}/Inputs/funcimport.ll"}
 
 ; The actual GUID values will depend on path to test.
 ; GUID-DAG: GUID {{.*}} is weakalias
diff --git a/llvm/test/Transforms/LowerTypeTests/cfi-icall-alias.ll b/llvm/test/Transforms/LowerTypeTests/cfi-icall-alias.ll
index 6b821186b0ad7..50f5d6445e29b 100644
--- a/llvm/test/Transforms/LowerTypeTests/cfi-icall-alias.ll
+++ b/llvm/test/Transforms/LowerTypeTests/cfi-icall-alias.ll
@@ -18,7 +18,7 @@ REGULAR: define private void @.cfi.jumptable()
 ;; CHECK that @llvm.type.test() is lowered to an actual check.
 RUN: opt test0.bc -passes=lowertypetests -lowertypetests-read-summary=exported.yaml \
 RUN:   -lowertypetests-summary-action=import -S -o - | FileCheck %s --check-prefix=THIN
-THIN:      define i1 @test() {
+THIN:      define i1 @test() !guid !{{.*}} {
 THIN-NEXT:   %1 = icmp eq i64 ptrtoint (ptr @alias to i64), ptrtoint (ptr @__typeid__ZTSFvvE_global_addr to i64)
 THIN-NEXT:   ret i1 %1
 THIN-NEXT: }
diff --git a/llvm/test/Transforms/PGOProfile/thinlto_indirect_call_promotion.ll b/llvm/test/Transforms/PGOProfile/thinlto_indirect_call_promotion.ll
index d2f4696ccf41d..159626134aaaf 100644
--- a/llvm/test/Transforms/PGOProfile/thinlto_indirect_call_promotion.ll
+++ b/llvm/test/Transforms/PGOProfile/thinlto_indirect_call_promotion.ll
@@ -23,8 +23,8 @@
 
 ; Test that callee with local linkage has `PGOFuncName` metadata while callee with external doesn't have it.
 ; RUN: llvm-dis lib.bc -o - | FileCheck %s --check-prefix=PGOName
-; PGOName-DAG: define void @_Z7callee1v() {{.*}} !prof ![[#]] {
-; PGOName-DAG: define internal void @_ZL7callee0v() {{.*}} !prof ![[#]] !PGOFuncName ![[#MD:]] {
+; PGOName-DAG: define void @_Z7callee1v() {{.*}} !prof ![[#]]
+; PGOName-DAG: define internal void @_ZL7callee0v() {{.*}} !prof ![[#]] !guid ![[#]] !PGOFuncName ![[#MD:]]
 ; The source filename of `lib.ll` is specified as "lib.cc" (i.e., the name does
 ; not change with the directory), so match the full name here.
 ; PGOName: ![[#MD]] = !{!"lib.cc;_ZL7callee0v"}
diff --git a/llvm/test/Transforms/PhaseOrdering/speculative-devirt-then-inliner.ll b/llvm/test/Transforms/PhaseOrdering/speculative-devirt-then-inliner.ll
index 98df729696de9..24b8b3c135cb3 100644
--- a/llvm/test/Transforms/PhaseOrdering/speculative-devirt-then-inliner.ll
+++ b/llvm/test/Transforms/PhaseOrdering/speculative-devirt-then-inliner.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -O3 -enable-devirtualize-speculatively %s 2>&1 | FileCheck %s
+; RUN: opt -S -passes="default<O3>" -enable-devirtualize-speculatively %s 2>&1 | FileCheck %s
 
 ; Test that the devirtualized calls are inlined.
 
diff --git a/llvm/test/Transforms/SampleProfile/ctxsplit.ll b/llvm/test/Transforms/SampleProfile/ctxsplit.ll
index 46e088a63e941..807fd7b73d37b 100644
--- a/llvm/test/Transforms/SampleProfile/ctxsplit.ll
+++ b/llvm/test/Transforms/SampleProfile/ctxsplit.ll
@@ -14,12 +14,12 @@
 ; POSTLINK: define dso_local noundef i32 @foo() {{.*}} !prof ![[ENTRY2:[0-9]+]] {
 ; POSTLINK: ![[ENTRY1]] = !{!"function_entry_count", i64 1001}
 ; POSTLINK: ![[ENTRY2]] = !{!"function_entry_count", i64 -1}
-; PRELINK: define dso_local noundef i32 @goo() {{.*}} !prof ![[ENTRY1:[0-9]+]] {
-; PRELINK: define dso_local noundef i32 @foo() {{.*}} !prof ![[ENTRY2:[0-9]+]] {
+; PRELINK: define dso_local noundef i32 @goo() {{.*}} !prof ![[ENTRY1:[0-9]+]]
+; PRELINK: define dso_local noundef i32 @foo() {{.*}} !prof ![[ENTRY2:[0-9]+]]
 ; PRELINK: ![[ENTRY1]] = !{!"function_entry_count", i64 1001}
 ; PRELINK: ![[ENTRY2]] = !{!"function_entry_count", i64 3001}
-; NOTHINLTO: define dso_local noundef i32 @goo() {{.*}} !prof ![[ENTRY1:[0-9]+]] {
-; NOTHINLTO: define dso_local noundef i32 @foo() {{.*}} !prof ![[ENTRY2:[0-9]+]] {
+; NOTHINLTO: define dso_local noundef i32 @goo() {{.*}} !prof ![[ENTRY1:[0-9]+]]
+; NOTHINLTO: define dso_local noundef i32 @foo() {{.*}} !prof ![[ENTRY2:[0-9]+]]
 ; NOTHINLTO: ![[ENTRY1]] = !{!"function_entry_count", i64 1001}
 ; NOTHINLTO: ![[ENTRY2]] = !{!"function_entry_count", i64 3001}
 
diff --git a/llvm/test/Transforms/ThinLTOBitcodeWriter/split-internal2.ll b/llvm/test/Transforms/ThinLTOBitcodeWriter/split-internal2.ll
index 3b3a7a0043ed0..c466fe05b2b32 100644
--- a/llvm/test/Transforms/ThinLTOBitcodeWriter/split-internal2.ll
+++ b/llvm/test/Transforms/ThinLTOBitcodeWriter/split-internal2.ll
@@ -20,7 +20,7 @@ target triple = "x86_64-unknown-linux-gnu"
 @g = global ptr @f, !type !0
 
 ; M0: define hidden void @f.13757e0fb71915e385efa4dc9d1e08fd()
-; M1: declare hidden void @f.13757e0fb71915e385efa4dc9d1e08fd()
+; M1: declare !guid !4 hidden void @f.13757e0fb71915e385efa4dc9d1e08fd()
 define internal void @f() {
   call void @f2()
   ret void
@@ -36,5 +36,5 @@ define internal void @f2() {
 
 ; test that the GUID of f.<hash> is the same in the summaries of the 2 split
 ; modules
-; M0: = gv: (name: "f.13757e0fb71915e385efa4dc9d1e08fd", {{.*}} ; guid = 11302379072751562722
-; M1: = gv: (name: "f.13757e0fb71915e385efa4dc9d1e08fd") ; guid = 11302379072751562722
+; M0: = gv: (name: "f.13757e0fb71915e385efa4dc9d1e08fd", {{.*}} ; guid = 11298141672137883075
+; M1: = gv: (name: "f.13757e0fb71915e385efa4dc9d1e08fd") ; guid = 11298141672137883075
diff --git a/llvm/test/Transforms/ThinLTOBitcodeWriter/split-vfunc.ll b/llvm/test/Transforms/ThinLTOBitcodeWriter/split-vfunc.ll
index 47c14be85c076..c62630eba191d 100644
--- a/llvm/test/Transforms/ThinLTOBitcodeWriter/split-vfunc.ll
+++ b/llvm/test/Transforms/ThinLTOBitcodeWriter/split-vfunc.ll
@@ -34,44 +34,44 @@ define i64 @ok2(ptr %this, i64 %arg) {
 declare { i64, i1 } @llvm.sadd.with.overflow.i64(i64, i64)
 
 ; M0: define void @wrongtype1
-; M1: declare void @wrongtype1()
+; M1: declare !guid !{{.*}} void @wrongtype1()
 define void @wrongtype1(ptr) {
   ret void
 }
 
 ; M0: define i128 @wrongtype2
-; M1: declare void @wrongtype2()
+; M1: declare !guid !{{.*}} void @wrongtype2()
 define i128 @wrongtype2(ptr) {
   ret i128 0
 }
 
 ; M0: define i64 @wrongtype3
-; M1: declare void @wrongtype3()
+; M1: declare !guid !{{.*}} void @wrongtype3()
 define i64 @wrongtype3() {
   ret i64 0
 }
 
 ; M0: define i64 @wrongtype4
-; M1: declare void @wrongtype4()
+; M1: declare !guid !{{.*}} void @wrongtype4()
 define i64 @wrongtype4(ptr, ptr) {
   ret i64 0
 }
 
 ; M0: define i64 @wrongtype5
-; M1: declare void @wrongtype5()
+; M1: declare !guid !{{.*}} void @wrongtype5()
 define i64 @wrongtype5(ptr, i128) {
   ret i64 0
 }
 
 ; M0: define i64 @usesthis
-; M1: declare void @usesthis()
+; M1: declare !guid !{{.*}} void @usesthis()
 define i64 @usesthis(ptr %this) {
   %i = ptrtoint ptr %this to i64
   ret i64 %i
 }
 
 ; M0: define i8 @reads
-; M1: declare void @reads()
+; M1: declare !guid !{{.*}} void @reads()
 define i8 @reads(ptr %this) {
   %l = load i8, ptr %this
   ret i8 %l
diff --git a/llvm/test/Transforms/ThinLTOBitcodeWriter/unsplittable.ll b/llvm/test/Transforms/ThinLTOBitcodeWriter/unsplittable.ll
index c961179fd3d07..430071d617777 100644
--- a/llvm/test/Transforms/ThinLTOBitcodeWriter/unsplittable.ll
+++ b/llvm/test/Transforms/ThinLTOBitcodeWriter/unsplittable.ll
@@ -21,7 +21,7 @@
 ; CHECK: @llvm.global_ctors = appending global
 @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @f, ptr null }]
 
-; CHECK: @g = internal global i8 42, !type !0
+; CHECK: @g = internal global i8 42, !type !1
 @g = internal global i8 42, !type !0
 
 declare void @sink(ptr)
diff --git a/llvm/test/Transforms/WholeProgramDevirt/branch-funnel-profile.ll b/llvm/test/Transforms/WholeProgramDevirt/branch-funnel-profile.ll
index f1a28ca8d681c..1b694812a42b5 100644
--- a/llvm/test/Transforms/WholeProgramDevirt/branch-funnel-profile.ll
+++ b/llvm/test/Transforms/WholeProgramDevirt/branch-funnel-profile.ll
@@ -6,28 +6,28 @@
 ; RUN: opt -passes=wholeprogramdevirt -whole-program-visibility -wholeprogramdevirt-summary-action=export -wholeprogramdevirt-read-summary=%S/Inputs/export.yaml -wholeprogramdevirt-write-summary=%t -S -o - %s | FileCheck --check-prefixes=RETP %s
 ; RUN: opt -passes='wholeprogramdevirt,default<O3>' -whole-program-visibility -wholeprogramdevirt-summary-action=export -wholeprogramdevirt-read-summary=%S/Inputs/export.yaml -wholeprogramdevirt-write-summary=%t  -S -o - %s | FileCheck --check-prefixes=O3 %s
 
-; RETP: define hidden void @__typeid_typeid1_0_branch_funnel(ptr nest %0, ...) !prof !11
-; RETP: define hidden void @__typeid_typeid1_rv_0_branch_funnel(ptr nest %0, ...) !prof !11
-; RETP: define internal void @branch_funnel(ptr nest %0, ...) !prof !10
-; RETP: define internal void @branch_funnel.1(ptr nest %0, ...) !prof !10 
-; RETP: !10 = !{!"function_entry_count", i64 1000}
-; RETP: !11 = !{!"function_entry_count", i64 3000}
-
-; NORETP: define hidden void @__typeid_typeid1_0_branch_funnel(ptr nest %0, ...) !prof !11
-; NORETP: define hidden void @__typeid_typeid1_rv_0_branch_funnel(ptr nest %0, ...) !prof !11
-; NORETP: define internal void @branch_funnel(ptr nest %0, ...) !prof !11
-; NORETP: define internal void @branch_funnel.1(ptr nest %0, ...) !prof !11
-; NORETP: !11 = !{!"unknown", !"wholeprogramdevirt"}
-
-; O3: define hidden void @__typeid_typeid1_0_branch_funnel(ptr nest %0, ...) local_unnamed_addr #5 !prof !11
-; O3: define hidden void @__typeid_typeid1_rv_0_branch_funnel(ptr nest %0, ...) local_unnamed_addr #5 !prof !11
-; O3: define internal void @branch_funnel(ptr nest %0, ...) unnamed_addr #5 !prof !10
-; O3: define internal void @branch_funnel.1(ptr nest %0, ...) unnamed_addr #5 !prof !10
-; O3: define hidden void @__typeid_typeid3_0_branch_funnel(ptr nest %0, ...) local_unnamed_addr #5 !prof !12
-; O3: define hidden void @__typeid_typeid3_rv_0_branch_funnel(ptr nest %0, ...) local_unnamed_addr #5 !prof !12
-; O3: !10 = !{!"function_entry_count", i64 1000}
-; O3: !11 = !{!"function_entry_count", i64 3000}
-; O3: !12 = !{!"unknown", !"wholeprogramdevirt"}
+; RETP: define hidden void @__typeid_typeid1_0_branch_funnel(ptr nest %0, ...) !prof ![[PROF1:[0-9]+]]
+; RETP: define hidden void @__typeid_typeid1_rv_0_branch_funnel(ptr nest %0, ...) !prof ![[PROF1]]
+; RETP: define internal void @branch_funnel(ptr nest %0, ...) !prof ![[PROF2:[0-9]+]]
+; RETP: define internal void @branch_funnel.1(ptr nest %0, ...) !prof ![[PROF2]]
+; RETP: ![[PROF2]] = !{!"function_entry_count", i64 1000}
+; RETP: ![[PROF1]] = !{!"function_entry_count", i64 3000}
+
+; NORETP: define hidden void @__typeid_typeid1_0_branch_funnel(ptr nest %0, ...) !prof ![[PROF1:[0-9]+]]
+; NORETP: define hidden void @__typeid_typeid1_rv_0_branch_funnel(ptr nest %0, ...) !prof ![[PROF1]]
+; NORETP: define internal void @branch_funnel(ptr nest %0, ...) !prof ![[PROF1]]
+; NORETP: define internal void @branch_funnel.1(ptr nest %0, ...) !prof ![[PROF1]]
+; NORETP: ![[PROF1]] = !{!"unknown", !"wholeprogramdevirt"}
+
+; O3: define hidden void @__typeid_typeid1_0_branch_funnel(ptr nest %0, ...) local_unnamed_addr #5 !prof ![[PROF1:[0-9]+]]
+; O3: define hidden void @__typeid_typeid1_rv_0_branch_funnel(ptr nest %0, ...) local_unnamed_addr #5 !prof ![[PROF1]]
+; O3: define internal void @branch_funnel(ptr nest %0, ...) unnamed_addr #5 !prof ![[PROF2:[0-9]+]]
+; O3: define internal void @branch_funnel.1(ptr nest %0, ...) unnamed_addr #5 !prof ![[PROF2]]
+; O3: define hidden void @__typeid_typeid3_0_branch_funnel(ptr nest %0, ...) local_unnamed_addr #5 !prof ![[PROF3:[0-9]+]]
+; O3: define hidden void @__typeid_typeid3_rv_0_branch_funnel(ptr nest %0, ...) local_unnamed_addr #5 !prof ![[PROF3]]
+; O3: ![[PROF2]] = !{!"function_entry_count", i64 1000}
+; O3: ![[PROF1]] = !{!"function_entry_count", i64 3000}
+; O3: ![[PROF3]] = !{!"unknown", !"wholeprogramdevirt"}
 
 target datalayout = "e-p:64:64"
 target triple = "x86_64-unknown-linux-gnu"
diff --git a/llvm/test/Transforms/WholeProgramDevirt/export-single-impl.ll b/llvm/test/Transforms/WholeProgramDevirt/export-single-impl.ll
index c27b4b34ac04e..d58adeecae9ab 100644
--- a/llvm/test/Transforms/WholeProgramDevirt/export-single-impl.ll
+++ b/llvm/test/Transforms/WholeProgramDevirt/export-single-impl.ll
@@ -81,12 +81,12 @@ define void @vf2(ptr) {
   ret void
 }
 
-; CHECK: define hidden void @vf3.llvm.merged(ptr %0) {
+; CHECK: define hidden void @vf3.llvm.merged(ptr %0)
 define internal void @vf3(ptr) {
   ret void
 }
 
-; CHECK: define hidden void @vf4.llvm.merged(ptr %0) comdat {
+; CHECK: define hidden void @vf4.llvm.merged(ptr %0) comdat
 define internal void @vf4(ptr) comdat {
   ret void
 }
diff --git a/llvm/test/Transforms/WholeProgramDevirt/export-vcp.ll b/llvm/test/Transforms/WholeProgramDevirt/export-vcp.ll
index 24aba548ea9ac..03dfdbf8314f9 100644
--- a/llvm/test/Transforms/WholeProgramDevirt/export-vcp.ll
+++ b/llvm/test/Transforms/WholeProgramDevirt/export-vcp.ll
@@ -60,10 +60,10 @@ target datalayout = "e-p:64:64"
 ; CHECK: [[CVT3D:.*]] = private constant { [8 x i8], ptr, [0 x i8] } { [8 x i8] c"\00\00\00\00\00\00\00\01", ptr @vf1i1, [0 x i8] zeroinitializer }, !type !0
 @vt3d = constant ptr @vf1i1, !type !0
 
-; CHECK: [[CVT4A:.*]] = private constant { [8 x i8], ptr, [0 x i8] } { [8 x i8] c"\00\00\00\00\01\00\00\00", ptr @vf1i32, [0 x i8] zeroinitializer }, !type !1
+; CHECK: [[CVT4A:.*]] = private constant { [8 x i8], ptr, [0 x i8] } { [8 x i8] c"\00\00\00\00\01\00\00\00", ptr @vf1i32, [0 x i8] zeroinitializer }, !type !5
 @vt4a = constant ptr @vf1i32, !type !1
 
-; CHECK: [[CVT4B:.*]] = private constant { [8 x i8], ptr, [0 x i8] } { [8 x i8] c"\00\00\00\00\02\00\00\00", ptr @vf2i32, [0 x i8] zeroinitializer }, !type !1
+; CHECK: [[CVT4B:.*]] = private constant { [8 x i8], ptr, [0 x i8] } { [8 x i8] c"\00\00\00\00\02\00\00\00", ptr @vf2i32, [0 x i8] zeroinitializer }, !type !5
 @vt4b = constant ptr @vf2i32, !type !1
 
 ; X86: @__typeid_typeid3_0_12_24_byte = hidden alias i8, inttoptr (i32 -1 to ptr)
@@ -96,7 +96,7 @@ define i32 @vf2i32(ptr %this, i32, i32) readnone {
 }
 
 ; CHECK: !0 = !{i32 8, !"typeid3"}
-; CHECK: !1 = !{i32 8, !"typeid4"}
+; CHECK: !5 = !{i32 8, !"typeid4"}
 
 !0 = !{i32 0, !"typeid3"}
 !1 = !{i32 0, !"typeid4"}
diff --git a/llvm/tools/llvm-link/llvm-link.cpp b/llvm/tools/llvm-link/llvm-link.cpp
index f6fc41d750b50..32b019a518dee 100644
--- a/llvm/tools/llvm-link/llvm-link.cpp
+++ b/llvm/tools/llvm-link/llvm-link.cpp
@@ -360,8 +360,10 @@ static bool importFunctions(const char *argv0, Module &DestModule) {
     // definition, so make the import type definition directly.
     // FIXME: A follow-up patch should add test coverage for import declaration
     // in `llvm-link` CLI (e.g., by introducing a new command line option).
+    const auto MaybeGUID = F->getGUIDIfAssigned();
+    const auto GUID = MaybeGUID ? *MaybeGUID : GlobalValue::getGUIDAssumingExternalLinkage(F->getName());
     ImportList.addDefinition(
-        FileNameStringCache.insert(FileName).first->getKey(), F->getGUID());
+        FileNameStringCache.insert(FileName).first->getKey(), GUID);
   }
   auto CachedModuleLoader = [&](StringRef Identifier) {
     return ModuleLoaderCache.takeModule(std::string(Identifier));
diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp
index 2f57ae6d045e3..0942047eab396 100644
--- a/llvm/tools/opt/NewPMDriver.cpp
+++ b/llvm/tools/opt/NewPMDriver.cpp
@@ -41,6 +41,7 @@
 #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
 #include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
 #include "llvm/Transforms/Scalar/LoopPassManager.h"
+#include "llvm/Transforms/Utils/AssignGUID.h"
 #include "llvm/Transforms/Utils/Debugify.h"
 #include "llvm/Transforms/Utils/ProfileVerify.h"
 
@@ -527,14 +528,21 @@ bool llvm::runPassPipeline(
   case OK_NoOutput:
     break; // No output pass needed.
   case OK_OutputAssembly:
+    if (EmitSummaryIndex) {
+      MPM.addPass(AssignGUIDPass());
+    }
     MPM.addPass(PrintModulePass(
         Out->os(), "", ShouldPreserveAssemblyUseListOrder, EmitSummaryIndex));
     break;
   case OK_OutputBitcode:
+    if (EmitSummaryIndex) {
+      MPM.addPass(AssignGUIDPass());
+    }
     MPM.addPass(BitcodeWriterPass(Out->os(), ShouldPreserveBitcodeUseListOrder,
                                   EmitSummaryIndex, EmitModuleHash));
     break;
   case OK_OutputThinLTOBitcode:
+    MPM.addPass(AssignGUIDPass());
     MPM.addPass(ThinLTOBitcodeWriterPass(
         Out->os(), ThinLTOLinkOut ? &ThinLTOLinkOut->os() : nullptr,
         ShouldPreserveBitcodeUseListOrder));

>From d3bac46f25541ff58cfc95d00571778ecf16cd75 Mon Sep 17 00:00:00 2001
From: orodley <orodley at google.com>
Date: Thu, 12 Mar 2026 23:44:29 +0000
Subject: [PATCH 2/7] Address review comments and formatting issues

---
 llvm/include/llvm/IR/GlobalValue.h            |  4 +++
 llvm/include/llvm/IR/Module.h                 | 17 ++++++++----
 llvm/include/llvm/IR/ModuleSummaryIndex.h     |  6 +++--
 llvm/lib/Analysis/CtxProfAnalysis.cpp         |  2 +-
 llvm/lib/AsmParser/LLParser.cpp               |  4 ++-
 llvm/lib/Bitcode/Reader/BitcodeReader.cpp     | 26 +++++++++++--------
 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp     |  6 +++--
 llvm/lib/IR/Globals.cpp                       | 14 ++++++----
 llvm/lib/LTO/LTO.cpp                          |  3 +--
 llvm/lib/LTO/LTOBackend.cpp                   |  3 ++-
 llvm/lib/Transforms/IPO/FunctionImport.cpp    | 25 +++++++++---------
 llvm/lib/Transforms/Utils/AssignGUID.cpp      |  7 ++---
 llvm/lib/Transforms/Utils/CloneModule.cpp     |  2 +-
 .../Transforms/Utils/FunctionImportUtils.cpp  | 25 +++++++++---------
 llvm/tools/llvm-link/llvm-link.cpp            |  4 ++-
 15 files changed, 87 insertions(+), 61 deletions(-)

diff --git a/llvm/include/llvm/IR/GlobalValue.h b/llvm/include/llvm/IR/GlobalValue.h
index acc836e1974d4..fd585fd403711 100644
--- a/llvm/include/llvm/IR/GlobalValue.h
+++ b/llvm/include/llvm/IR/GlobalValue.h
@@ -615,6 +615,10 @@ class GlobalValue : public Constant {
   /// Return a 64-bit global unique ID for this value. It is based on the
   /// "original" name and linkage of this value (i.e. whenever its GUID was
   /// assigned). This might not match the current name and linkage.
+  ///
+  /// The \c AssignGUIDPass must be run before this is called, otherwise
+  /// GUIDs won't be available. This pass can be run multiple times as it does
+  /// nothing if GUID metadata is already present.
   GUID getGUID() const;
 
   /// Return the GUID for this value if it has been assigned, nullopt
diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h
index b4a13128dd9f7..d68d98ae097d8 100644
--- a/llvm/include/llvm/IR/Module.h
+++ b/llvm/include/llvm/IR/Module.h
@@ -577,21 +577,28 @@ class LLVM_ABI Module {
   // Use global_size() to get the total number of global variables.
   // Use globals() to get the range of all global variables.
 
-  std::optional<GlobalValue::GUID> getGUID(const Value* V) const {
+  std::optional<GlobalValue::GUID> getGUID(const Value *V) const {
     const auto It = ValueToGUIDMap.find(V);
     if (It == ValueToGUIDMap.end()) {
-      return {};
+      return std::nullopt;
     }
 
     return It->getSecond();
   }
 
-  void insertGUID(const Value* V, GlobalValue::GUID GUID) {
-    ValueToGUIDMap[V] = GUID;
+  void insertGUID(const Value *V, GlobalValue::GUID GUID) {
+    const auto [It, WasInserted] = ValueToGUIDMap.insert({V, GUID});
+    
+    (void)It, (void)WasInserted;
+  #ifndef NDEBUG
+    if (!WasInserted) {
+      assert((It->second == GUID) && "insertGUID called with different value");
+    }
+  #endif
   }
 
 private:
-  DenseMap<const Value*, GlobalValue::GUID> ValueToGUIDMap;
+  DenseMap<const Value *, GlobalValue::GUID> ValueToGUIDMap;
 
 /// @}
 /// @name Direct access to the globals list, functions list, and symbol table
diff --git a/llvm/include/llvm/IR/ModuleSummaryIndex.h b/llvm/include/llvm/IR/ModuleSummaryIndex.h
index be204e8a52aa8..c242c26498c69 100644
--- a/llvm/include/llvm/IR/ModuleSummaryIndex.h
+++ b/llvm/include/llvm/IR/ModuleSummaryIndex.h
@@ -1770,8 +1770,10 @@ class ModuleSummaryIndex {
     return ValueInfo(HaveGVs, VP);
   }
 
-  /// Return a ValueInfo for \p GV with GUID \p GUID and mark it as belonging to GV.
-  ValueInfo getOrInsertValueInfo(const GlobalValue *GV, GlobalValue::GUID GUID) {
+  /// Return a ValueInfo for \p GV with GUID \p GUID and mark it as belonging to
+  /// GV.
+  ValueInfo getOrInsertValueInfo(const GlobalValue *GV,
+                                 GlobalValue::GUID GUID) {
     assert(HaveGVs);
     auto VP = getOrInsertValuePtr(GUID);
     VP->second.U.GV = GV;
diff --git a/llvm/lib/Analysis/CtxProfAnalysis.cpp b/llvm/lib/Analysis/CtxProfAnalysis.cpp
index d4c00e4090220..9df6ab048d382 100644
--- a/llvm/lib/Analysis/CtxProfAnalysis.cpp
+++ b/llvm/lib/Analysis/CtxProfAnalysis.cpp
@@ -50,7 +50,7 @@ static cl::opt<bool> ForceIsInSpecializedModule(
     "ctx-profile-force-is-specialized", cl::init(false),
     cl::desc("Treat the given module as-if it were containing the "
              "post-thinlink module containing the root"));
- 
+
 class ProfileAnnotatorImpl final {
   friend class ProfileAnnotator;
   class BBInfo;
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index fcfa2ec2be342..00d17c0b808e8 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -9851,7 +9851,9 @@ bool LLParser::addGlobalValueToIndex(
       // Be a little lenient here, to accomodate older files without GUIDs
       // already computed and assigned as metadata.
       auto MaybeGUID = GV->getGUIDIfAssigned();
-      GUID = MaybeGUID ? *MaybeGUID : GlobalValue::getGUIDAssumingExternalLinkage(GV->getName());
+      GUID = MaybeGUID
+                 ? *MaybeGUID
+                 : GlobalValue::getGUIDAssumingExternalLinkage(GV->getName());
 
       VI = Index->getOrInsertValueInfo(GV, GUID);
     } else {
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 2b0406f853832..9102308e63b00 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -978,6 +978,8 @@ class ModuleSummaryIndexBitcodeReader : public BitcodeReaderBase {
   /// Callback to ask whether a symbol is the prevailing copy when invoked
   /// during combined index building.
   std::function<bool(StringRef)> IsPrevailing = nullptr;
+  
+  /// Callback invoked whenever a new ValueInfo is generated.
   std::function<void(ValueInfo)> OnValueInfo = nullptr;
 
   /// Saves the stack ids from the STACK_IDS record to consult when adding
@@ -993,9 +995,9 @@ class ModuleSummaryIndexBitcodeReader : public BitcodeReaderBase {
   /// list and used to avoid repeated hash lookups.
   std::vector<unsigned> StackIdToIndex;
 
-   /// A list of GUIDs defined by this module. Indexed by ValueID.
-   std::vector<uint64_t> DefinedGUIDs;
- 
+  /// A list of GUIDs defined by this module. Indexed by ValueID.
+  std::vector<uint64_t> DefinedGUIDs;
+
 public:
   ModuleSummaryIndexBitcodeReader(
       BitstreamCursor Stream, StringRef Strtab, ModuleSummaryIndex &TheIndex,
@@ -4050,9 +4052,10 @@ Error BitcodeReader::globalCleanup() {
 
   for (size_t ValueID = 0; ValueID < GUIDList.size(); ValueID++) {
     const auto GUID = GUIDList[ValueID];
-    if (GUID == 0) continue;
+    if (GUID == 0)
+      continue;
 
-    const auto* Value = ValueList[ValueID];
+    const auto *Value = ValueList[ValueID];
     TheModule->insertGUID(Value, GUID);
   }
 
@@ -7282,13 +7285,14 @@ void ModuleSummaryIndexBitcodeReader::setValueGUID(
     ValueGUID = DefinedGUIDs[ValueID];
   if (ValueGUID == 0)
     ValueGUID = GlobalValue::getGUIDAssumingExternalLinkage(
-      GlobalValue::getGlobalIdentifier(ValueName, Linkage, SourceFileName));
+        GlobalValue::getGlobalIdentifier(ValueName, Linkage, SourceFileName));
 
   auto OriginalNameID = ValueGUID;
   if (GlobalValue::isLocalLinkage(Linkage))
     OriginalNameID = GlobalValue::getGUIDAssumingExternalLinkage(ValueName);
   if (PrintSummaryGUIDs)
-    dbgs() << "GUID " << ValueGUID << "(" << OriginalNameID << ") is " << ValueName << "\n";
+    dbgs() << "GUID " << ValueGUID << "(" << OriginalNameID << ") is "
+           << ValueName << "\n";
 
   // UseStrtab is false for legacy summary formats and value names are
   // created on stack. In that case we save the name in a string saver in
@@ -8720,10 +8724,10 @@ BitcodeModule::getLazyModule(LLVMContext &Context, bool ShouldLazyLoadMetadata,
 // We don't use ModuleIdentifier here because the client may need to control the
 // module path used in the combined summary (e.g. when reading summaries for
 // regular LTO modules).
-Error BitcodeModule::readSummary(
-    ModuleSummaryIndex &CombinedIndex, StringRef ModulePath,
-    std::function<bool(StringRef)> IsPrevailing,
-    std::function<void(ValueInfo)> OnValueInfo) {
+Error BitcodeModule::readSummary(ModuleSummaryIndex &CombinedIndex,
+                                 StringRef ModulePath,
+                                 std::function<bool(StringRef)> IsPrevailing,
+                                 std::function<void(ValueInfo)> OnValueInfo) {
   BitstreamCursor Stream(Buffer);
   if (Error JumpFailed = Stream.JumpToBit(ModuleBit))
     return JumpFailed;
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 338d94639514a..45f1a13b3db56 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -4592,7 +4592,8 @@ void ModuleBitcodeWriterBase::writePerModuleFunctionSummaryRecord(
 
 static GlobalValue::GUID getOrComputeGUID(const GlobalValue& V) {
   auto MaybeGUID = V.getGUIDIfAssigned();
-  return MaybeGUID ? *MaybeGUID : GlobalValue::getGUIDAssumingExternalLinkage(V.getName());
+  return MaybeGUID ? *MaybeGUID
+                   : GlobalValue::getGUIDAssumingExternalLinkage(V.getName());
 }
 
 // Collect the global value references in the given variable's initializer,
@@ -4919,7 +4920,8 @@ void ModuleBitcodeWriterBase::writeGUIDList() {
     } else {
       GUID = 0;
     }
-    if (GUID == 0) continue;
+    if (GUID == 0)
+      continue;
 
     const auto ValueID = VE.getValueID(&GV);
     GUIDs[ValueID] = GUID;
diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp
index b62ad1ccb26a6..2ec1eeb6daa12 100644
--- a/llvm/lib/IR/Globals.cpp
+++ b/llvm/lib/IR/Globals.cpp
@@ -103,19 +103,23 @@ std::optional<GlobalValue::GUID> GlobalValue::getGUIDIfAssigned() const {
   auto *MD = getMetadata(LLVMContext::MD_unique_id);
   if (MD != nullptr)
     return cast<ConstantInt>(cast<ConstantAsMetadata>(MD->getOperand(0))
-                                ->getValue()
-                                ->stripPointerCasts())
+                                 ->getValue()
+                                 ->stripPointerCasts())
         ->getZExtValue();
 
   // Handle a few special cases where we just want to compute it based on the
   // current properties.
-  if (isDeclaration() || isa<GlobalAlias>(this) || getName().starts_with("llvm.")) {
+  // TODO: Maybe we should use a more robust check for intrinsics than just
+  // matching on the name?
+  if (isDeclaration() || isa<GlobalAlias>(this) ||
+      getName().starts_with("llvm.")) {
     return GlobalValue::getGUIDAssumingExternalLinkage(getGlobalIdentifier());
   }
-  
+
   // Otherwise we try to look it up in the module, for cases where we've read
   // the GUID table but not the metadata.
-  if (getParent() == nullptr) return {};
+  if (getParent() == nullptr)
+    return {};
   const Module &M = *getParent();
 
   return M.getGUID(this);
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index 4c6a3f874121f..0dedf0a6e1a40 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -1209,8 +1209,7 @@ LTO::addThinLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
         // Find the summary in the module for this very GV and record the new
         // linkage so that we can switch it when we import the GV.
         if (R.LinkerRedefined)
-          if (auto *S = ThinLTO.CombinedIndex.findSummaryInModule(
-                  GUID, BMID))
+          if (auto *S = ThinLTO.CombinedIndex.findSummaryInModule(GUID, BMID))
             S->setLinkage(GlobalValue::WeakAnyLinkage);
       }
 
diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index 0373af7dfee8c..0e1d9dc554659 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -609,7 +609,8 @@ static void dropDeadSymbols(Module &Mod, const GVSummaryMapTy &DefinedGlobals,
 
   for (auto &GV : Mod.global_values()) {
     auto GUID = Mod.getGUID(&GV);
-    if (!GUID) continue;
+    if (!GUID)
+      continue;
 
     if (GlobalValueSummary *GVS = DefinedGlobals.lookup(*GUID))
       if (!Index.isGlobalValueLive(GVS)) {
diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp
index a1c7c664ee947..8aa24da63ed41 100644
--- a/llvm/lib/Transforms/IPO/FunctionImport.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp
@@ -1879,19 +1879,18 @@ static void internalizeGVsAfterImport(Module &M) {
     }
 }
 
-static GlobalValue::GUID getGUIDOrFallback(const GlobalValue& GV) {
-    // Modules compiled against the current version should have a GUID table
-    // and hence have the GUID available simply by calling getGUID(). But we
-    // want to support running on old bitcode files which have no embedded
-    // GUIDs. So if it's missing we fall back to computing the GUID with its
-    // current name / linkage type.
-    const auto MaybeGUID = GV.getGUIDIfAssigned();
-    return MaybeGUID ? *MaybeGUID
-        : GlobalValue::getGUIDAssumingExternalLinkage(
-            GlobalValue::getGlobalIdentifier(
-              GV.getName(),
-              GV.getLinkage(),
-              GV.getParent()->getSourceFileName()));
+static GlobalValue::GUID getGUIDOrFallback(const GlobalValue &GV) {
+  // Modules compiled against the current version should have a GUID table
+  // and hence have the GUID available simply by calling getGUID(). But we
+  // want to support running on old bitcode files which have no embedded
+  // GUIDs. So if it's missing we fall back to computing the GUID with its
+  // current name / linkage type.
+  const auto MaybeGUID = GV.getGUIDIfAssigned();
+  return MaybeGUID ? *MaybeGUID
+                   : GlobalValue::getGUIDAssumingExternalLinkage(
+                         GlobalValue::getGlobalIdentifier(
+                             GV.getName(), GV.getLinkage(),
+                             GV.getParent()->getSourceFileName()));
 }
 
 // Automatically import functions in Module \p DestModule based on the summaries
diff --git a/llvm/lib/Transforms/Utils/AssignGUID.cpp b/llvm/lib/Transforms/Utils/AssignGUID.cpp
index 7a7dba15c64fb..eb2c4844c1c87 100644
--- a/llvm/lib/Transforms/Utils/AssignGUID.cpp
+++ b/llvm/lib/Transforms/Utils/AssignGUID.cpp
@@ -6,9 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file provides a pass which assigns a a GUID (globally unique identifier)
-// to every GlobalValue in the module, according to its current name, linkage,
-// and originating file.
+// This file provides a pass which assigns GUID (globally unique identifier)
+// metadata to every GlobalValue in the module, according to its current name,
+// linkage, and originating file. It is idempotent -- if GUID metadata is
+// already present, it does nothing.
 //
 //===----------------------------------------------------------------------===//
 
diff --git a/llvm/lib/Transforms/Utils/CloneModule.cpp b/llvm/lib/Transforms/Utils/CloneModule.cpp
index 6768f6fff580a..7ffb4f1da662d 100644
--- a/llvm/lib/Transforms/Utils/CloneModule.cpp
+++ b/llvm/lib/Transforms/Utils/CloneModule.cpp
@@ -143,7 +143,7 @@ std::unique_ptr<Module> llvm::CloneModule(
     }
 
     if (!ShouldCloneDefinition(&I)) {
-      CopyMD();            
+      CopyMD();
       // Skip after setting the correct linkage for an external reference.
       F->setLinkage(GlobalValue::ExternalLinkage);
       // Personality function is not valid on a declaration.
diff --git a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
index 72f9b7be7f432..7e44fc3a8626d 100644
--- a/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
+++ b/llvm/lib/Transforms/Utils/FunctionImportUtils.cpp
@@ -166,19 +166,18 @@ FunctionImportGlobalProcessing::getPromotedName(const GlobalValue *SGV) {
       ImportIndex.getModuleHash(SGV->getParent()->getModuleIdentifier()));
 }
 
-static GlobalValue::GUID getGUIDOrFallback(const GlobalValue& GV) {
-    // Modules compiled against the current version should have a GUID table
-    // and hence have the GUID available simply by calling getGUID(). But we
-    // want to support running on old bitcode files which have no embedded
-    // GUIDs. So if it's missing we fall back to computing the GUID with its
-    // current name / linkage type.
-    const auto MaybeGUID = GV.getGUIDIfAssigned();
-    return MaybeGUID ? *MaybeGUID
-        : GlobalValue::getGUIDAssumingExternalLinkage(
-            GlobalValue::getGlobalIdentifier(
-              GV.getName(),
-              GV.getLinkage(),
-              GV.getParent()->getSourceFileName()));
+static GlobalValue::GUID getGUIDOrFallback(const GlobalValue &GV) {
+  // Modules compiled against the current version should have a GUID table
+  // and hence have the GUID available simply by calling getGUID(). But we
+  // want to support running on old bitcode files which have no embedded
+  // GUIDs. So if it's missing we fall back to computing the GUID with its
+  // current name / linkage type.
+  const auto MaybeGUID = GV.getGUIDIfAssigned();
+  return MaybeGUID ? *MaybeGUID
+                   : GlobalValue::getGUIDAssumingExternalLinkage(
+                         GlobalValue::getGlobalIdentifier(
+                             GV.getName(), GV.getLinkage(),
+                             GV.getParent()->getSourceFileName()));
 }
 
 GlobalValue::LinkageTypes
diff --git a/llvm/tools/llvm-link/llvm-link.cpp b/llvm/tools/llvm-link/llvm-link.cpp
index 32b019a518dee..2cbf8a3db37f0 100644
--- a/llvm/tools/llvm-link/llvm-link.cpp
+++ b/llvm/tools/llvm-link/llvm-link.cpp
@@ -361,7 +361,9 @@ static bool importFunctions(const char *argv0, Module &DestModule) {
     // FIXME: A follow-up patch should add test coverage for import declaration
     // in `llvm-link` CLI (e.g., by introducing a new command line option).
     const auto MaybeGUID = F->getGUIDIfAssigned();
-    const auto GUID = MaybeGUID ? *MaybeGUID : GlobalValue::getGUIDAssumingExternalLinkage(F->getName());
+    const auto GUID =
+        MaybeGUID ? *MaybeGUID
+                  : GlobalValue::getGUIDAssumingExternalLinkage(F->getName());
     ImportList.addDefinition(
         FileNameStringCache.insert(FileName).first->getKey(), GUID);
   }

>From 3c44a084264c484eea7b17b1f8078867da847abf Mon Sep 17 00:00:00 2001
From: orodley <orodley at google.com>
Date: Fri, 13 Mar 2026 03:55:34 +0000
Subject: [PATCH 3/7] More formatting fixes

---
 llvm/include/llvm/IR/Module.h             | 12 ++++++------
 llvm/lib/Bitcode/Reader/BitcodeReader.cpp |  2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h
index d68d98ae097d8..81f1c26bef8c8 100644
--- a/llvm/include/llvm/IR/Module.h
+++ b/llvm/include/llvm/IR/Module.h
@@ -588,21 +588,21 @@ class LLVM_ABI Module {
 
   void insertGUID(const Value *V, GlobalValue::GUID GUID) {
     const auto [It, WasInserted] = ValueToGUIDMap.insert({V, GUID});
-    
+
     (void)It, (void)WasInserted;
-  #ifndef NDEBUG
+#ifndef NDEBUG
     if (!WasInserted) {
       assert((It->second == GUID) && "insertGUID called with different value");
     }
-  #endif
+#endif
   }
 
 private:
   DenseMap<const Value *, GlobalValue::GUID> ValueToGUIDMap;
 
-/// @}
-/// @name Direct access to the globals list, functions list, and symbol table
-/// @{
+  /// @}
+  /// @name Direct access to the globals list, functions list, and symbol table
+  /// @{
 
   /// Get the Module's list of global variables (constant).
   const GlobalListType   &getGlobalList() const       { return GlobalList; }
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 9102308e63b00..819571e6141aa 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -978,7 +978,7 @@ class ModuleSummaryIndexBitcodeReader : public BitcodeReaderBase {
   /// Callback to ask whether a symbol is the prevailing copy when invoked
   /// during combined index building.
   std::function<bool(StringRef)> IsPrevailing = nullptr;
-  
+
   /// Callback invoked whenever a new ValueInfo is generated.
   std::function<void(ValueInfo)> OnValueInfo = nullptr;
 

>From 44efd5b0daf2ab4d29faa1783d63913bc05fb028 Mon Sep 17 00:00:00 2001
From: orodley <orodley at google.com>
Date: Fri, 13 Mar 2026 04:05:30 +0000
Subject: [PATCH 4/7] Ditto

---
 llvm/lib/Transforms/IPO/FunctionImport.cpp | 39 +++++++++++-----------
 1 file changed, 20 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp
index 8aa24da63ed41..b183f8072bc81 100644
--- a/llvm/lib/Transforms/IPO/FunctionImport.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp
@@ -2004,26 +2004,27 @@ Expected<bool> FunctionImporter::importFunctions(
         bool ImportDefinition =
             MaybeImportType == GlobalValueSummary::Definition;
 
-       LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not")
-                         << " importing alias"
-                         << (ImportDefinition
-                                 ? " definition "
-                                 : (MaybeImportType ? " declaration " : " "))
-                         << GUID << " " << GA.getName() << " from "
-                         << SrcModule->getSourceFileName() << "\n");
-       if (ImportDefinition) {
-         if (Error Err = GA.materialize())
-           return std::move(Err);
-         // Import alias as a copy of its aliasee.
-         GlobalObject *GO = GA.getAliaseeObject();
-         if (Error Err = GO->materialize())
-           return std::move(Err);
-         auto *Fn = replaceAliasWithAliasee(SrcModule.get(), &GA);
-         assert(Fn);
-         (void)Fn;
-         LLVM_DEBUG(dbgs() << "Is importing aliasee fn " << getGUIDOrFallback(*GO) << " "
-                           << GO->getName() << " from "
+        LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not")
+                          << " importing alias"
+                          << (ImportDefinition
+                                  ? " definition "
+                                  : (MaybeImportType ? " declaration " : " "))
+                          << GUID << " " << GA.getName() << " from "
                           << SrcModule->getSourceFileName() << "\n");
+        if (ImportDefinition) {
+          if (Error Err = GA.materialize())
+            return std::move(Err);
+          // Import alias as a copy of its aliasee.
+          GlobalObject *GO = GA.getAliaseeObject();
+          if (Error Err = GO->materialize())
+            return std::move(Err);
+          auto *Fn = replaceAliasWithAliasee(SrcModule.get(), &GA);
+          assert(Fn);
+          (void)Fn;
+          LLVM_DEBUG(dbgs()
+                     << "Is importing aliasee fn " << getGUIDOrFallback(*GO)
+                     << " " << GO->getName() << " from "
+                     << SrcModule->getSourceFileName() << "\n");
           if (EnableImportMetadata || EnableMemProfContextDisambiguation) {
             // Add 'thinlto_src_module' and 'thinlto_src_file' metadata for
             // statistics and debugging.

>From 95189e6e6762ae1996ea63814ffb22debd3fdd6d Mon Sep 17 00:00:00 2001
From: orodley <orodley at google.com>
Date: Fri, 13 Mar 2026 04:08:21 +0000
Subject: [PATCH 5/7] And again

---
 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 45f1a13b3db56..77935e7cf583e 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -4590,7 +4590,7 @@ void ModuleBitcodeWriterBase::writePerModuleFunctionSummaryRecord(
       /*WriteContextSizeInfoIndex*/ true, CallStackPos, CallStackCount);
 }
 
-static GlobalValue::GUID getOrComputeGUID(const GlobalValue& V) {
+static GlobalValue::GUID getOrComputeGUID(const GlobalValue &V) {
   auto MaybeGUID = V.getGUIDIfAssigned();
   return MaybeGUID ? *MaybeGUID
                    : GlobalValue::getGUIDAssumingExternalLinkage(V.getName());

>From 77674d8126fd20d662d21f574a676513fc188508 Mon Sep 17 00:00:00 2001
From: orodley <orodley at google.com>
Date: Mon, 23 Mar 2026 04:50:37 +0000
Subject: [PATCH 6/7] Fix lld tests

---
 llvm/include/llvm/LTO/LTO.h                |  1 +
 llvm/lib/LTO/LTO.cpp                       | 26 ++++++++++++------
 llvm/lib/Transforms/IPO/FunctionImport.cpp | 32 +++++++++++-----------
 3 files changed, 34 insertions(+), 25 deletions(-)

diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h
index 32a47b3c87e1d..0335fd593865a 100644
--- a/llvm/include/llvm/LTO/LTO.h
+++ b/llvm/include/llvm/LTO/LTO.h
@@ -589,6 +589,7 @@ class LTO {
                             IRName, GlobalValue::LinkageTypes::ExternalLinkage,
                             ""));
     }
+
     /// Special partition numbers.
     enum : unsigned {
       /// A partition number has not yet been assigned to this global.
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index 0dedf0a6e1a40..d502aba6df3f8 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -1126,17 +1126,25 @@ Error LTO::linkRegularLTO(RegularLTOState::AddedModule Mod,
   llvm::TimeTraceScope timeScope("LTO link regular LTO");
   std::vector<GlobalValue *> Keep;
   for (GlobalValue *GV : Mod.Keep) {
-    if (LivenessFromIndex && !ThinLTO.CombinedIndex.isGUIDLive(GV->getGUID())) {
-      if (Function *F = dyn_cast<Function>(GV)) {
-        if (DiagnosticOutputFile) {
-          if (Error Err = F->materialize())
-            return Err;
-          auto R = OptimizationRemark(DEBUG_TYPE, "deadfunction", F);
-          R << ore::NV("Function", F) << " not added to the combined module ";
-          emitRemark(R);
+    if (LivenessFromIndex) {
+      const auto MaybeGUID = GV->getGUIDIfAssigned();
+      const auto GUID =
+          MaybeGUID ? *MaybeGUID
+                    : GlobalValue::getGUIDAssumingExternalLinkage(
+                          GlobalValue::getGlobalIdentifier(
+                              GV->getName(), GlobalValue::ExternalLinkage, ""));
+      if (!ThinLTO.CombinedIndex.isGUIDLive(GUID)) {
+        if (Function *F = dyn_cast<Function>(GV)) {
+          if (DiagnosticOutputFile) {
+            if (Error Err = F->materialize())
+              return Err;
+            auto R = OptimizationRemark(DEBUG_TYPE, "deadfunction", F);
+            R << ore::NV("Function", F) << " not added to the combined module ";
+            emitRemark(R);
+          }
         }
+        continue;
       }
-      continue;
     }
 
     if (!GV->hasAvailableExternallyLinkage()) {
diff --git a/llvm/lib/Transforms/IPO/FunctionImport.cpp b/llvm/lib/Transforms/IPO/FunctionImport.cpp
index b183f8072bc81..1e5d15c2e9efd 100644
--- a/llvm/lib/Transforms/IPO/FunctionImport.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionImport.cpp
@@ -338,6 +338,20 @@ selectCallee(const ModuleSummaryIndex &Index,
   return nullptr;
 }
 
+static GlobalValue::GUID getGUIDOrFallback(const GlobalValue &GV) {
+  // Modules compiled against the current version should have a GUID table
+  // and hence have the GUID available simply by calling getGUID(). But we
+  // want to support running on old bitcode files which have no embedded
+  // GUIDs. So if it's missing we fall back to computing the GUID with its
+  // current name / linkage type.
+  const auto MaybeGUID = GV.getGUIDIfAssigned();
+  return MaybeGUID ? *MaybeGUID
+                   : GlobalValue::getGUIDAssumingExternalLinkage(
+                         GlobalValue::getGlobalIdentifier(
+                             GV.getName(), GV.getLinkage(),
+                             GV.getParent()->getSourceFileName()));
+}
+
 namespace {
 
 using EdgeInfo = std::tuple<const FunctionSummary *, unsigned /* Threshold */>;
@@ -1681,7 +1695,7 @@ void llvm::thinLTOFinalizeInModule(Module &TheModule,
   DenseSet<Comdat *> NonPrevailingComdats;
   auto FinalizeInModule = [&](GlobalValue &GV, bool Propagate = false) {
     // See if the global summary analysis computed a new resolved linkage.
-    const auto &GS = DefinedGlobals.find(GV.getGUID());
+    const auto &GS = DefinedGlobals.find(getGUIDOrFallback(GV));
     if (GS == DefinedGlobals.end())
       return;
 
@@ -1818,7 +1832,7 @@ void llvm::thinLTOInternalizeModule(Module &TheModule,
       return true;
 
     // Lookup the linkage recorded in the summaries during global analysis.
-    auto GS = DefinedGlobals.find(GV.getGUID());
+    auto GS = DefinedGlobals.find(getGUIDOrFallback(GV));
     if (GS == DefinedGlobals.end()) {
       // Must have been promoted (possibly conservatively). Find original
       // name so that we can access the correct summary and see if it can
@@ -1879,20 +1893,6 @@ static void internalizeGVsAfterImport(Module &M) {
     }
 }
 
-static GlobalValue::GUID getGUIDOrFallback(const GlobalValue &GV) {
-  // Modules compiled against the current version should have a GUID table
-  // and hence have the GUID available simply by calling getGUID(). But we
-  // want to support running on old bitcode files which have no embedded
-  // GUIDs. So if it's missing we fall back to computing the GUID with its
-  // current name / linkage type.
-  const auto MaybeGUID = GV.getGUIDIfAssigned();
-  return MaybeGUID ? *MaybeGUID
-                   : GlobalValue::getGUIDAssumingExternalLinkage(
-                         GlobalValue::getGlobalIdentifier(
-                             GV.getName(), GV.getLinkage(),
-                             GV.getParent()->getSourceFileName()));
-}
-
 // Automatically import functions in Module \p DestModule based on the summaries
 // index.
 Expected<bool> FunctionImporter::importFunctions(

>From 2e22ce8db6a137c614df28d670813d95b78772b7 Mon Sep 17 00:00:00 2001
From: orodley <orodley at google.com>
Date: Mon, 30 Mar 2026 04:24:43 +0000
Subject: [PATCH 7/7] Fix clang tests

---
 clang/lib/CodeGen/CGCUDANV.cpp                |  6 ++++-
 .../CodeGen/cfi-icall-trap-recover-runtime.c  | 24 +++++++++----------
 clang/test/CodeGen/lto-newpm-pipeline.c       |  3 +++
 .../cfi-vcall-trap-recover-runtime.cpp        | 12 +++++-----
 4 files changed, 26 insertions(+), 19 deletions(-)

diff --git a/clang/lib/CodeGen/CGCUDANV.cpp b/clang/lib/CodeGen/CGCUDANV.cpp
index e04da90b3cbf6..284355f6a6791 100644
--- a/clang/lib/CodeGen/CGCUDANV.cpp
+++ b/clang/lib/CodeGen/CGCUDANV.cpp
@@ -25,6 +25,7 @@
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/GlobalValue.h"
 #include "llvm/IR/ReplaceConstant.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/VirtualFileSystem.h"
@@ -969,7 +970,10 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() {
     // Generate a unique module ID.
     SmallString<64> ModuleID;
     llvm::raw_svector_ostream OS(ModuleID);
-    OS << ModuleIDPrefix << llvm::format("%" PRIx64, FatbinWrapper->getGUID());
+    OS << ModuleIDPrefix
+       << llvm::format("%" PRIx64,
+                       llvm::GlobalValue::getGUIDAssumingExternalLinkage(
+                           FatbinWrapper->getName()));
     llvm::Constant *ModuleIDConstant = makeConstantArray(
         std::string(ModuleID), "", ModuleIDSectionName, 32, /*AddNull=*/true);
 
diff --git a/clang/test/CodeGen/cfi-icall-trap-recover-runtime.c b/clang/test/CodeGen/cfi-icall-trap-recover-runtime.c
index 2c44842f9d28e..5717fc66488af 100644
--- a/clang/test/CodeGen/cfi-icall-trap-recover-runtime.c
+++ b/clang/test/CodeGen/cfi-icall-trap-recover-runtime.c
@@ -15,32 +15,32 @@
 
 
 // TRAP-LABEL: define hidden void @f(
-// TRAP-SAME: ) #[[ATTR0:[0-9]+]] !type [[META6:![0-9]+]] !type [[META7:![0-9]+]] {
+// TRAP-SAME: ) #[[ATTR0:[0-9]+]] !type [[META6:![0-9]+]] !type [[META7:![0-9]+]]
 // TRAP-NEXT:  [[ENTRY:.*:]]
 // TRAP-NEXT:    ret void
 //
 // ABORT-LABEL: define hidden void @f(
-// ABORT-SAME: ) #[[ATTR0:[0-9]+]] !type [[META6:![0-9]+]] !type [[META7:![0-9]+]] {
+// ABORT-SAME: ) #[[ATTR0:[0-9]+]] !type [[META6:![0-9]+]] !type [[META7:![0-9]+]]
 // ABORT-NEXT:  [[ENTRY:.*:]]
 // ABORT-NEXT:    ret void
 //
 // RECOVER-LABEL: define hidden void @f(
-// RECOVER-SAME: ) #[[ATTR0:[0-9]+]] !type [[META6:![0-9]+]] !type [[META7:![0-9]+]] {
+// RECOVER-SAME: ) #[[ATTR0:[0-9]+]] !type [[META6:![0-9]+]] !type [[META7:![0-9]+]]
 // RECOVER-NEXT:  [[ENTRY:.*:]]
 // RECOVER-NEXT:    ret void
 //
 // ABORT_MIN-LABEL: define hidden void @f(
-// ABORT_MIN-SAME: ) #[[ATTR0:[0-9]+]] !type [[META6:![0-9]+]] !type [[META7:![0-9]+]] {
+// ABORT_MIN-SAME: ) #[[ATTR0:[0-9]+]] !type [[META6:![0-9]+]] !type [[META7:![0-9]+]]
 // ABORT_MIN-NEXT:  [[ENTRY:.*:]]
 // ABORT_MIN-NEXT:    ret void
 //
 // RECOVER_MIN-LABEL: define hidden void @f(
-// RECOVER_MIN-SAME: ) #[[ATTR0:[0-9]+]] !type [[META6:![0-9]+]] !type [[META7:![0-9]+]] {
+// RECOVER_MIN-SAME: ) #[[ATTR0:[0-9]+]] !type [[META6:![0-9]+]] !type [[META7:![0-9]+]]
 // RECOVER_MIN-NEXT:  [[ENTRY:.*:]]
 // RECOVER_MIN-NEXT:    ret void
 //
 // PRESERVE_MIN-LABEL: define hidden void @f(
-// PRESERVE_MIN-SAME: ) #[[ATTR0:[0-9]+]] !type [[META6:![0-9]+]] !type [[META7:![0-9]+]] {
+// PRESERVE_MIN-SAME: ) #[[ATTR0:[0-9]+]] !type [[META6:![0-9]+]] !type [[META7:![0-9]+]]
 // PRESERVE_MIN-NEXT:  [[ENTRY:.*:]]
 // PRESERVE_MIN-NEXT:    ret void
 //
@@ -50,7 +50,7 @@ void f() {
 void xf();
 
 // TRAP-LABEL: define hidden void @g(
-// TRAP-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] !type [[META8:![0-9]+]] !type [[META9:![0-9]+]] {
+// TRAP-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] !type [[META8:![0-9]+]] !type [[META9:![0-9]+]]
 // TRAP-NEXT:  [[ENTRY:.*:]]
 // TRAP-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
 // TRAP-NEXT:    [[FP:%.*]] = alloca ptr, align 8
@@ -71,7 +71,7 @@ void xf();
 // TRAP-NEXT:    ret void
 //
 // ABORT-LABEL: define hidden void @g(
-// ABORT-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] !type [[META8:![0-9]+]] !type [[META9:![0-9]+]] {
+// ABORT-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] !type [[META8:![0-9]+]] !type [[META9:![0-9]+]]
 // ABORT-NEXT:  [[ENTRY:.*:]]
 // ABORT-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
 // ABORT-NEXT:    [[FP:%.*]] = alloca ptr, align 8
@@ -93,7 +93,7 @@ void xf();
 // ABORT-NEXT:    ret void
 //
 // RECOVER-LABEL: define hidden void @g(
-// RECOVER-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] !type [[META8:![0-9]+]] !type [[META9:![0-9]+]] {
+// RECOVER-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] !type [[META8:![0-9]+]] !type [[META9:![0-9]+]]
 // RECOVER-NEXT:  [[ENTRY:.*:]]
 // RECOVER-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
 // RECOVER-NEXT:    [[FP:%.*]] = alloca ptr, align 8
@@ -115,7 +115,7 @@ void xf();
 // RECOVER-NEXT:    ret void
 //
 // ABORT_MIN-LABEL: define hidden void @g(
-// ABORT_MIN-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] !type [[META8:![0-9]+]] !type [[META9:![0-9]+]] {
+// ABORT_MIN-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] !type [[META8:![0-9]+]] !type [[META9:![0-9]+]]
 // ABORT_MIN-NEXT:  [[ENTRY:.*:]]
 // ABORT_MIN-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
 // ABORT_MIN-NEXT:    [[FP:%.*]] = alloca ptr, align 8
@@ -136,7 +136,7 @@ void xf();
 // ABORT_MIN-NEXT:    ret void
 //
 // RECOVER_MIN-LABEL: define hidden void @g(
-// RECOVER_MIN-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] !type [[META8:![0-9]+]] !type [[META9:![0-9]+]] {
+// RECOVER_MIN-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] !type [[META8:![0-9]+]] !type [[META9:![0-9]+]]
 // RECOVER_MIN-NEXT:  [[ENTRY:.*:]]
 // RECOVER_MIN-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
 // RECOVER_MIN-NEXT:    [[FP:%.*]] = alloca ptr, align 8
@@ -157,7 +157,7 @@ void xf();
 // RECOVER_MIN-NEXT:    ret void
 //
 // PRESERVE_MIN-LABEL: define hidden void @g(
-// PRESERVE_MIN-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] !type [[META8:![0-9]+]] !type [[META9:![0-9]+]] {
+// PRESERVE_MIN-SAME: i32 noundef [[B:%.*]]) #[[ATTR0]] !type [[META8:![0-9]+]] !type [[META9:![0-9]+]]
 // PRESERVE_MIN-NEXT:  [[ENTRY:.*:]]
 // PRESERVE_MIN-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
 // PRESERVE_MIN-NEXT:    [[FP:%.*]] = alloca ptr, align 8
diff --git a/clang/test/CodeGen/lto-newpm-pipeline.c b/clang/test/CodeGen/lto-newpm-pipeline.c
index ea9784a76f923..c8ee5e949ae87 100644
--- a/clang/test/CodeGen/lto-newpm-pipeline.c
+++ b/clang/test/CodeGen/lto-newpm-pipeline.c
@@ -34,6 +34,7 @@
 // CHECK-FULL-O0-NEXT: Running pass: CoroConditionalWrapper
 // CHECK-FULL-O0-NEXT: Running pass: CanonicalizeAliasesPass
 // CHECK-FULL-O0-NEXT: Running pass: NameAnonGlobalPass
+// CHECK-FULL-O0-NEXT: Running pass: AssignGUIDPass
 // CHECK-FULL-O0-NEXT: Running pass: AnnotationRemarksPass
 // CHECK-FULL-O0-NEXT: Running analysis: TargetLibraryAnalysis
 // CHECK-FULL-O0-NEXT: Running pass: VerifierPass
@@ -48,6 +49,7 @@
 // CHECK-THIN-O0-NEXT: Running pass: CoroConditionalWrapper
 // CHECK-THIN-O0-NEXT: Running pass: CanonicalizeAliasesPass
 // CHECK-THIN-O0-NEXT: Running pass: NameAnonGlobalPass
+// CHECK-THIN-O0-NEXT: Running pass: AssignGUIDPass
 // CHECK-THIN-O0-NEXT: Running pass: AnnotationRemarksPass
 // CHECK-THIN-O0-NEXT: Running analysis: TargetLibraryAnalysis
 // CHECK-THIN-O0-NEXT: Running pass: VerifierPass
@@ -64,6 +66,7 @@
 // CHECK-THIN-OPTIMIZED-NOT: Running pass: LoopVectorizePass
 // CHECK-THIN-OPTIMIZED: Running pass: CanonicalizeAliasesPass
 // CHECK-THIN-OPTIMIZED: Running pass: NameAnonGlobalPass
+// CHECK-THIN-OPTIMIZED: Running pass: AssignGUIDPass
 // CHECK-THIN-OPTIMIZED: Running pass: ThinLTOBitcodeWriterPass
 
 void Foo(void) {}
diff --git a/clang/test/CodeGenCXX/cfi-vcall-trap-recover-runtime.cpp b/clang/test/CodeGenCXX/cfi-vcall-trap-recover-runtime.cpp
index 2451d31e9a489..a1e1563a4f38d 100644
--- a/clang/test/CodeGenCXX/cfi-vcall-trap-recover-runtime.cpp
+++ b/clang/test/CodeGenCXX/cfi-vcall-trap-recover-runtime.cpp
@@ -19,7 +19,7 @@ struct S1 {
 };
 
 // TRAP-LABEL: define hidden void @_Z3s1fP2S1(
-// TRAP-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]] {
+// TRAP-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]]
 // TRAP-NEXT:  [[ENTRY:.*:]]
 // TRAP-NEXT:    [[S1_ADDR:%.*]] = alloca ptr, align 8
 // TRAP-NEXT:    store ptr [[S1]], ptr [[S1_ADDR]], align 8
@@ -37,7 +37,7 @@ struct S1 {
 // TRAP-NEXT:    ret void
 //
 // ABORT-LABEL: define hidden void @_Z3s1fP2S1(
-// ABORT-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]] {
+// ABORT-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]]
 // ABORT-NEXT:  [[ENTRY:.*:]]
 // ABORT-NEXT:    [[S1_ADDR:%.*]] = alloca ptr, align 8
 // ABORT-NEXT:    store ptr [[S1]], ptr [[S1_ADDR]], align 8
@@ -58,7 +58,7 @@ struct S1 {
 // ABORT-NEXT:    ret void
 //
 // RECOVER-LABEL: define hidden void @_Z3s1fP2S1(
-// RECOVER-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]] {
+// RECOVER-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]]
 // RECOVER-NEXT:  [[ENTRY:.*:]]
 // RECOVER-NEXT:    [[S1_ADDR:%.*]] = alloca ptr, align 8
 // RECOVER-NEXT:    store ptr [[S1]], ptr [[S1_ADDR]], align 8
@@ -79,7 +79,7 @@ struct S1 {
 // RECOVER-NEXT:    ret void
 //
 // ABORT_MIN-LABEL: define hidden void @_Z3s1fP2S1(
-// ABORT_MIN-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]] {
+// ABORT_MIN-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]]
 // ABORT_MIN-NEXT:  [[ENTRY:.*:]]
 // ABORT_MIN-NEXT:    [[S1_ADDR:%.*]] = alloca ptr, align 8
 // ABORT_MIN-NEXT:    store ptr [[S1]], ptr [[S1_ADDR]], align 8
@@ -98,7 +98,7 @@ struct S1 {
 // ABORT_MIN-NEXT:    ret void
 //
 // RECOVER_MIN-LABEL: define hidden void @_Z3s1fP2S1(
-// RECOVER_MIN-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]] {
+// RECOVER_MIN-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]]
 // RECOVER_MIN-NEXT:  [[ENTRY:.*:]]
 // RECOVER_MIN-NEXT:    [[S1_ADDR:%.*]] = alloca ptr, align 8
 // RECOVER_MIN-NEXT:    store ptr [[S1]], ptr [[S1_ADDR]], align 8
@@ -117,7 +117,7 @@ struct S1 {
 // RECOVER_MIN-NEXT:    ret void
 //
 // PRESERVE_MIN-LABEL: define hidden void @_Z3s1fP2S1(
-// PRESERVE_MIN-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]] {
+// PRESERVE_MIN-SAME: ptr noundef [[S1:%.*]]) #[[ATTR0:[0-9]+]]
 // PRESERVE_MIN-NEXT:  [[ENTRY:.*:]]
 // PRESERVE_MIN-NEXT:    [[S1_ADDR:%.*]] = alloca ptr, align 8
 // PRESERVE_MIN-NEXT:    store ptr [[S1]], ptr [[S1_ADDR]], align 8



More information about the cfe-commits mailing list