[flang-commits] [clang] [flang] [llvm] [mlir] [polly] Reland "[IR] Use persistent metadata IDs for printing" (PR #220390)

Yaxun Liu via flang-commits flang-commits at lists.llvm.org
Wed Sep 2 05:31:14 PDT 2026


https://github.com/yxsamliu updated https://github.com/llvm/llvm-project/pull/220390

>From 436f28c9d3c3e74ac8b1b40f57c96ef30436a65a Mon Sep 17 00:00:00 2001
From: "Yaxun (Sam) Liu" <yaxun.liu at amd.com>
Date: Tue, 1 Sep 2026 20:38:07 +0000
Subject: [PATCH] Reland "[IR] Use persistent metadata IDs for printing"

This relands 85e903099313aa5ea98d175698aaa40e27a0d743 with fixes for
the buildbot failures that prompted its revert.

Move the MachineModuleSlotTracker debug-location query out of line so
DILocation is complete when SmallPtrSet pointer traits are instantiated
by MSVC.

The legacy DXIL pretty-printer renumbers persistent metadata IDs, which
changes module print state. Make the pass report the modification and
register it as a transformation rather than an analysis.

Repeated pass and debug printing currently rebuilds metadata slot
numbers by scanning the module. On large modules, this repeated setup
can take more time than printing the requested function.

Store a persistent print ID in each metadata node and use that ID
whenever metadata is printed. Before final assembly output, renumber the
IDs into canonical compact order so normal textual IR output remains
unchanged.

This keeps metadata numbers stable across pass snapshots while avoiding
repeated module-wide metadata scans.

Buildbot failure:
https://lab.llvm.org/buildbot/#/builders/2/builds/60795
Buildbot failure:
https://lab.llvm.org/buildbot/#/builders/187/builds/23268
---
 clang/lib/CodeGen/BackendUtil.cpp             |   7 +-
 clang/tools/cir-translate/cir-translate.cpp   |   1 +
 .../clang-fuzzer/handle-llvm/handle_llvm.cpp  |   5 +-
 .../clang-import-test/clang-import-test.cpp   |   4 +-
 .../include/flang/Optimizer/CodeGen/CodeGen.h |   8 +-
 flang/lib/Frontend/FrontendActions.cpp        |   6 +-
 .../llvm/CodeGen/MachineModuleSlotTracker.h   |  23 +-
 llvm/include/llvm/IR/IRPrintingPasses.h       |   5 +
 llvm/include/llvm/IR/Metadata.h               |  10 +-
 llvm/include/llvm/IR/Module.h                 |   5 +
 llvm/include/llvm/IR/ModuleSlotTracker.h      |  52 ++-
 .../include/llvm/IRPrinter/IRPrintingPasses.h |   7 +-
 llvm/lib/CodeGen/MIRParser/MIParser.cpp       |   4 +-
 llvm/lib/CodeGen/MIRPrintingPass.cpp          |  16 +
 llvm/lib/CodeGen/MachineBasicBlock.cpp        |   2 +-
 llvm/lib/CodeGen/MachineModuleSlotTracker.cpp | 116 ++---
 llvm/lib/CodeGen/MachineOperand.cpp           |   2 +-
 llvm/lib/IR/AsmWriter.cpp                     | 412 ++++++++++--------
 llvm/lib/IR/Core.cpp                          |   2 +
 llvm/lib/IR/IRPrintingPasses.cpp              |  71 +--
 llvm/lib/IR/LLVMContextImpl.cpp               |   9 +
 llvm/lib/IR/LLVMContextImpl.h                 |  18 +
 llvm/lib/IR/Metadata.cpp                      |  17 +
 llvm/lib/IR/MetadataImpl.h                    |   2 +
 llvm/lib/IR/SSAContext.cpp                    |   2 +-
 llvm/lib/IRPrinter/IRPrintingPasses.cpp       |  20 +-
 llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp | 112 ++++-
 .../DirectX/DebugInfo/di-globalvariable.ll    |   7 +
 llvm/test/CodeGen/Hexagon/swp-no-alias.mir    |   8 +-
 llvm/test/CodeGen/MIR/AMDGPU/instr-mmra.mir   |   2 +-
 .../CodeGen/MIR/AMDGPU/machine-metadata.mir   |  12 +-
 .../MIR/X86/instr-heap-alloc-operands.mir     |   2 +-
 .../test/CodeGen/MIR/X86/instr-pcsections.mir |   2 +-
 .../MIR/X86/instructions-debug-location.mir   |  14 +-
 .../test/CodeGen/MIR/X86/machine-metadata.mir |  36 +-
 llvm/test/CodeGen/MIR/X86/mem-cache-hint.mir  |   4 +-
 llvm/test/CodeGen/MIR/X86/memory-operands.mir |  10 +-
 .../CodeGen/MIR/X86/metadata-operands.mir     |   2 +-
 llvm/test/CodeGen/MIR/X86/pr38773.mir         |   4 +-
 .../MIR/X86/stack-object-debug-info.mir       |   4 +-
 .../AArch64/no-dbg-value-after-terminator.mir |   2 +-
 .../legacy-callgraph-scc-pass-printer.ll      |  13 +-
 .../print-changed-persistent-metadata-ids.ll  |  77 ++++
 .../Other/print-persistent-metadata-ids.ll    |  94 ++++
 .../Inputs/loop-distribute.ll.expected        |   6 +-
 .../IR/01-ir-print-basic-details.test         |  22 +-
 .../IR/01-ir-select-logical-elements.test     |  16 +-
 .../IR/02-ir-logical-lines.test               |   4 +-
 .../IR/06-ir-full-logical-view.test           |  22 +-
 llvm/tools/llvm-dis/llvm-dis.cpp              |   1 +
 llvm/tools/llvm-extract/llvm-extract.cpp      |   6 +-
 llvm/tools/llvm-link/llvm-link.cpp            |   1 +
 llvm/tools/llvm-reduce/ReducerWorkItem.cpp    |   9 +-
 llvm/tools/llvm-split/llvm-split.cpp          |   7 +-
 llvm/tools/llvm-stress/llvm-stress.cpp        |   1 +
 llvm/tools/opt/NewPMDriver.cpp                |   3 +-
 llvm/tools/opt/optdriver.cpp                  |   7 +-
 .../verify-uselistorder.cpp                   |   9 +-
 llvm/unittests/AsmParser/AsmParserTest.cpp    |  33 ++
 llvm/unittests/IR/AsmWriterTest.cpp           | 124 ++++++
 llvm/unittests/IR/MetadataTest.cpp            |  18 +-
 llvm/unittests/IR/ModuleTest.cpp              |  55 +++
 llvm/unittests/MIR/MachineMetadata.cpp        | 107 +++--
 mlir/lib/Target/LLVMIR/ConvertToLLVMIR.cpp    |   1 +
 .../Target/LLVMIR/Import/import-failure.ll    |  24 +-
 polly/test/ForwardOpTree/atax.ll              |  16 +-
 polly/test/ForwardOpTree/jacobi-1d.ll         |   8 +-
 ...eserve-equiv-class-order-in-basic_block.ll |   4 +-
 .../stmt_split_exit_of_region_stmt.ll         |   2 +-
 .../ScopInfo/stmt_split_no_after_split.ll     |   2 +-
 .../test/ScopInfo/stmt_split_no_dependence.ll |   2 +-
 .../stmt_split_phi_in_beginning_bb.ll         |   2 +-
 polly/test/ScopInfo/stmt_split_phi_in_stmt.ll |   2 +-
 .../ScopInfo/stmt_split_scalar_dependence.ll  |   2 +-
 polly/test/ScopInfo/stmt_split_within_loop.ll |   2 +-
 75 files changed, 1242 insertions(+), 507 deletions(-)
 create mode 100644 llvm/test/Other/print-changed-persistent-metadata-ids.ll
 create mode 100644 llvm/test/Other/print-persistent-metadata-ids.ll

diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 6aa6bc1bd41e8..086f886be4390 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -1166,7 +1166,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
             *OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr));
       } else if (Action == Backend_EmitLL) {
         MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists,
-                                    /*EmitLTOSummary=*/true));
+                                    /*EmitLTOSummary=*/true,
+                                    /*ShouldRenumberMetadata=*/true));
       }
     } else {
       // Emit a module summary by default for Regular LTO except for ld64
@@ -1184,7 +1185,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
                                       EmitLTOSummary));
       } else if (Action == Backend_EmitLL) {
         MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists,
-                                    EmitLTOSummary));
+                                    EmitLTOSummary,
+                                    /*ShouldRenumberMetadata=*/true));
       }
     }
 
@@ -1456,6 +1458,7 @@ runThinLTOBackend(CompilerInstance &CI, ModuleSummaryIndex *CombinedIndex,
     break;
   case Backend_EmitLL:
     Conf.PreCodeGenModuleHook = [&](size_t Task, const llvm::Module &Mod) {
+      M->renumberMetadataForAssembly();
       M->print(*OS, nullptr, CGOpts.EmitLLVMUseLists);
       return false;
     };
diff --git a/clang/tools/cir-translate/cir-translate.cpp b/clang/tools/cir-translate/cir-translate.cpp
index 4452741d7433e..a58512e3fca22 100644
--- a/clang/tools/cir-translate/cir-translate.cpp
+++ b/clang/tools/cir-translate/cir-translate.cpp
@@ -165,6 +165,7 @@ void registerToLLVMTranslation() {
                                                       enableOpenMP);
         if (!llvmModule)
           return mlir::failure();
+        llvmModule->renumberMetadataForAssembly();
         llvmModule->print(output, nullptr);
         return mlir::success();
       },
diff --git a/clang/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp b/clang/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp
index 942e35c30e19f..1c745bffe00c0 100644
--- a/clang/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp
+++ b/clang/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp
@@ -103,7 +103,10 @@ static void RunOptimizationPasses(raw_ostream &OS, Module &M,
   PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
 
   ModulePassManager MPM = PB.buildPerModuleDefaultPipeline(OL);
-  MPM.addPass(PrintModulePass(OS));
+  MPM.addPass(PrintModulePass(OS, /*Banner=*/"",
+                              /*ShouldPreserveUseListOrder=*/false,
+                              /*EmitSummaryIndex=*/false,
+                              /*ShouldRenumberMetadata=*/true));
 
   MPM.run(M, MAM);
 }
diff --git a/clang/tools/clang-import-test/clang-import-test.cpp b/clang/tools/clang-import-test/clang-import-test.cpp
index 8e83687d3e96a..bcb5d2bdb8952 100644
--- a/clang/tools/clang-import-test/clang-import-test.cpp
+++ b/clang/tools/clang-import-test/clang-import-test.cpp
@@ -338,8 +338,10 @@ llvm::Expected<CIAndOrigins> Parse(const std::string &Path,
   if (llvm::Error PE = ParseSource(Path, CI.getCompilerInstance(), Consumers))
     return std::move(PE);
   CI.getDiagnosticClient().EndSourceFile();
-  if (ShouldDumpIR)
+  if (ShouldDumpIR) {
+    CG.GetModule()->renumberMetadataForAssembly();
     CG.GetModule()->print(llvm::outs(), nullptr);
+  }
   if (CI.getDiagnosticClient().getNumErrors())
     return llvm::make_error<llvm::StringError>(
         "Errors occurred while parsing the expression.", std::error_code());
diff --git a/flang/include/flang/Optimizer/CodeGen/CodeGen.h b/flang/include/flang/Optimizer/CodeGen/CodeGen.h
index 1d36788fb84f9..6ef575f5391d9 100644
--- a/flang/include/flang/Optimizer/CodeGen/CodeGen.h
+++ b/flang/include/flang/Optimizer/CodeGen/CodeGen.h
@@ -90,9 +90,11 @@ using LLVMIRLoweringPrinter =
 
 /// Convert the LLVM IR dialect to LLVM-IR proper
 std::unique_ptr<mlir::Pass> createLLVMDialectToLLVMPass(
-    llvm::raw_ostream &output,
-    LLVMIRLoweringPrinter printer =
-        [](llvm::Module &m, llvm::raw_ostream &out) { m.print(out, nullptr); });
+    llvm::raw_ostream &output, LLVMIRLoweringPrinter printer =
+                                   [](llvm::Module &m, llvm::raw_ostream &out) {
+                                     m.renumberMetadataForAssembly();
+                                     m.print(out, nullptr);
+                                   });
 
 /// Populate the given list with patterns that convert from FIR to LLVM.
 void populateFIRToLLVMConversionPatterns(
diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index 35e0e4004d9a0..108b1b4559d48 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -1094,9 +1094,9 @@ void CodeGenAction::runOptimizationPipeline(llvm::raw_pwrite_stream &os) {
             os, /*ShouldPreserveUseListOrder=*/false, emitSummary));
       }
     } else if (action == BackendActionTy::Backend_EmitLL) {
-      mpm.addPass(llvm::PrintModulePass(os, /*Banner=*/"",
-                                        /*ShouldPreserveUseListOrder=*/false,
-                                        emitSummary));
+      mpm.addPass(llvm::PrintModulePass(
+          os, /*Banner=*/"", /*ShouldPreserveUseListOrder=*/false, emitSummary,
+          /*ShouldRenumberMetadata=*/true));
     }
   }
 
diff --git a/llvm/include/llvm/CodeGen/MachineModuleSlotTracker.h b/llvm/include/llvm/CodeGen/MachineModuleSlotTracker.h
index 666b3caf67e27..7f52727cfef81 100644
--- a/llvm/include/llvm/CodeGen/MachineModuleSlotTracker.h
+++ b/llvm/include/llvm/CodeGen/MachineModuleSlotTracker.h
@@ -10,12 +10,13 @@
 #define LLVM_CODEGEN_MACHINEMODULESLOTTRACKER_H
 
 #include "llvm/ADT/STLFunctionalExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/IR/ModuleSlotTracker.h"
 #include "llvm/Support/Compiler.h"
 
 namespace llvm {
 
-class AbstractSlotTrackerStorage;
 class Function;
 class MachineModuleInfo;
 class MachineFunction;
@@ -24,24 +25,22 @@ class Module;
 using MFGetterFnT = function_ref<MachineFunction *(const Function &)>;
 
 class LLVM_ABI MachineModuleSlotTracker : public ModuleSlotTracker {
-  const Function &TheFunction;
   const MachineFunction *TheMF;
-  unsigned MDNStartSlot = 0, MDNEndSlot = 0;
+  MachineMDNodeListType MachineMDNodes;
+  SmallPtrSet<const DILocation *, 4> InlineDebugLocations;
 
-  void processMachineFunctionMetadata(AbstractSlotTrackerStorage *AST,
-                                      const MachineFunction &MF);
-  void processMachineModule(AbstractSlotTrackerStorage *AST, const Module *M,
-                            bool ShouldInitializeAllMetadata);
-  void processMachineFunction(AbstractSlotTrackerStorage *AST,
-                              const Function *F,
-                              bool ShouldInitializeAllMetadata);
+  void collectMachineFunctionMetadata(
+      SmallVectorImpl<const MDNode *> &Metadata, const MachineFunction &MF,
+      SmallVectorImpl<const MDNode *> *DebugLocations = nullptr) const;
 
 public:
-  MachineModuleSlotTracker(MFGetterFnT Fn, const MachineFunction *MF,
-                           bool ShouldInitializeAllMetadata = true);
+  MachineModuleSlotTracker(MFGetterFnT Fn, const MachineFunction *MF);
   ~MachineModuleSlotTracker() override;
 
+  /// Renumber module and machine metadata for canonical MIR output.
+  void renumberMetadataForAssembly();
   void collectMachineMDNodes(MachineMDNodeListType &L) const;
+  bool shouldPrintDebugLocationInline(const DILocation *DL) const override;
 };
 
 } // namespace llvm
diff --git a/llvm/include/llvm/IR/IRPrintingPasses.h b/llvm/include/llvm/IR/IRPrintingPasses.h
index 1b2d38d6190e9..0eb60f55f74c3 100644
--- a/llvm/include/llvm/IR/IRPrintingPasses.h
+++ b/llvm/include/llvm/IR/IRPrintingPasses.h
@@ -31,6 +31,11 @@ LLVM_ABI ModulePass *
 createPrintModulePass(raw_ostream &OS, const std::string &Banner = "",
                       bool ShouldPreserveUseListOrder = false);
 
+LLVM_ABI ModulePass *createPrintModulePass(raw_ostream &OS,
+                                           const std::string &Banner,
+                                           bool ShouldPreserveUseListOrder,
+                                           bool ShouldRenumberMetadata);
+
 /// Create and return a pass that prints functions to the specified
 /// \c raw_ostream as they are processed.
 LLVM_ABI FunctionPass *createPrintFunctionPass(raw_ostream &OS,
diff --git a/llvm/include/llvm/IR/Metadata.h b/llvm/include/llvm/IR/Metadata.h
index 5b458fa14f0b1..a53cb63ed59cf 100644
--- a/llvm/include/llvm/IR/Metadata.h
+++ b/llvm/include/llvm/IR/Metadata.h
@@ -1079,11 +1079,11 @@ class MDNode : public Metadata {
   /// Explicity set alignment because bitfields by default have an
   /// alignment of 1 on z/OS.
   struct alignas(alignof(size_t)) Header {
-    size_t IsResizable : 1;
-    size_t IsLarge : 1;
-    size_t SmallSize : 4;
-    size_t SmallNumOps : 4;
-    size_t : sizeof(size_t) * CHAR_BIT - 10;
+    uint32_t IsResizable : 1;
+    uint32_t IsLarge : 1;
+    uint32_t SmallSize : 4;
+    uint32_t SmallNumOps : 4;
+    uint32_t MetadataPrintID;
 
     unsigned NumUnresolved = 0;
     using LargeStorageVector = SmallVector<MDOperand, 0>;
diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h
index e009fb4a4c3e3..3f5d762759751 100644
--- a/llvm/include/llvm/IR/Module.h
+++ b/llvm/include/llvm/IR/Module.h
@@ -991,6 +991,11 @@ class LLVM_ABI Module {
              bool ShouldPreserveUseListOrder = false,
              bool IsForDebug = false) const;
 
+  /// Renumber the IDs stored in metadata nodes into canonical assembly order.
+  /// This mutates the IDs and should only be used immediately before final
+  /// assembly output.
+  void renumberMetadataForAssembly();
+
   /// Dump the module to stderr (for debugging).
   void dump() const;
 
diff --git a/llvm/include/llvm/IR/ModuleSlotTracker.h b/llvm/include/llvm/IR/ModuleSlotTracker.h
index a3882a81e1177..b92bd16084b06 100644
--- a/llvm/include/llvm/IR/ModuleSlotTracker.h
+++ b/llvm/include/llvm/IR/ModuleSlotTracker.h
@@ -9,11 +9,12 @@
 #ifndef LLVM_IR_MODULESLOTTRACKER_H
 #define LLVM_IR_MODULESLOTTRACKER_H
 
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/Compiler.h"
 #include <functional>
 #include <memory>
 #include <utility>
-#include <vector>
 
 namespace llvm {
 
@@ -21,6 +22,7 @@ class Module;
 class Function;
 class SlotTracker;
 class Value;
+class DILocation;
 class MDNode;
 
 /// Abstract interface of slot tracker storage.
@@ -28,8 +30,6 @@ class LLVM_ABI AbstractSlotTrackerStorage {
 public:
   virtual ~AbstractSlotTrackerStorage();
 
-  virtual unsigned getNextMetadataSlot() = 0;
-
   virtual void createMetadataSlot(const MDNode *) = 0;
   virtual int getMetadataSlot(const MDNode *) = 0;
 };
@@ -43,20 +43,37 @@ class LLVM_ABI AbstractSlotTrackerStorage {
 /// If the IR changes from underneath \a ModuleSlotTracker, strings like
 /// "<badref>" will be printed, or, worse, the wrong slots entirely.
 class LLVM_ABI ModuleSlotTracker {
+public:
+  using MachineMDNodeListType =
+      SmallVector<std::pair<unsigned, const MDNode *>, 0>;
+
+private:
   /// Storage for a slot tracker.
   std::unique_ptr<SlotTracker> MachineStorage;
   bool ShouldCreateStorage = false;
-  bool ShouldInitializeAllMetadata = false;
 
   const Module *M = nullptr;
   const Function *F = nullptr;
   SlotTracker *Machine = nullptr;
 
-  std::function<void(AbstractSlotTrackerStorage *, const Module *, bool)>
+  std::function<void(AbstractSlotTrackerStorage *, const Module *)>
       ProcessModuleHookFn;
-  std::function<void(AbstractSlotTrackerStorage *, const Function *, bool)>
+  std::function<void(AbstractSlotTrackerStorage *, const Function *)>
       ProcessFunctionHookFn;
 
+protected:
+  /// Renumber module metadata and then additional metadata for canonical
+  /// assembly output.
+  void renumberMetadataForAssembly(
+      ArrayRef<const MDNode *> AdditionalMetadata,
+      MachineMDNodeListType *AdditionalMetadataNodes = nullptr) const;
+
+  /// Collect metadata reachable from \p AdditionalMetadata but not from the
+  /// module.
+  void collectAdditionalMetadata(
+      ArrayRef<const MDNode *> AdditionalMetadata,
+      MachineMDNodeListType &AdditionalMetadataNodes) const;
+
 public:
   /// Wrap a preinitialized SlotTracker.
   ModuleSlotTracker(SlotTracker &Machine, const Module *M,
@@ -64,13 +81,8 @@ class LLVM_ABI ModuleSlotTracker {
 
   /// Construct a slot tracker from a module.
   ///
-  /// If \a M is \c nullptr, uses a null slot tracker.  Otherwise, initializes
-  /// a slot tracker, and initializes all metadata slots.  \c
-  /// ShouldInitializeAllMetadata defaults to true because this is expected to
-  /// be shared between multiple callers, and otherwise MDNode references will
-  /// not match up.
-  explicit ModuleSlotTracker(const Module *M,
-                             bool ShouldInitializeAllMetadata = true);
+  /// If \a M is \c nullptr, uses a null slot tracker.
+  explicit ModuleSlotTracker(const Module *M);
 
   /// Destructor to clean up storage.
   virtual ~ModuleSlotTracker();
@@ -95,14 +107,16 @@ class LLVM_ABI ModuleSlotTracker {
   int getLocalSlot(const Value *V);
 
   void setProcessHook(
-      std::function<void(AbstractSlotTrackerStorage *, const Module *, bool)>);
-  void setProcessHook(std::function<void(AbstractSlotTrackerStorage *,
-                                         const Function *, bool)>);
+      std::function<void(AbstractSlotTrackerStorage *, const Module *)>);
+  void setProcessHook(
+      std::function<void(AbstractSlotTrackerStorage *, const Function *)>);
 
-  using MachineMDNodeListType =
-      std::vector<std::pair<unsigned, const MDNode *>>;
+  void collectMDNodes(MachineMDNodeListType &L) const;
 
-  void collectMDNodes(MachineMDNodeListType &L, unsigned LB, unsigned UB) const;
+  /// Return whether a debug location should be printed inline instead of by ID.
+  virtual bool shouldPrintDebugLocationInline(const DILocation *) const {
+    return false;
+  }
 };
 
 } // end namespace llvm
diff --git a/llvm/include/llvm/IRPrinter/IRPrintingPasses.h b/llvm/include/llvm/IRPrinter/IRPrintingPasses.h
index e574d94ca2f22..56fdd94187dd3 100644
--- a/llvm/include/llvm/IRPrinter/IRPrintingPasses.h
+++ b/llvm/include/llvm/IRPrinter/IRPrintingPasses.h
@@ -35,13 +35,16 @@ class PrintModulePass : public RequiredPassInfoMixin<PrintModulePass> {
   std::string Banner;
   bool ShouldPreserveUseListOrder;
   bool EmitSummaryIndex;
+  bool ShouldRenumberMetadata;
 
 public:
   LLVM_ABI PrintModulePass();
+  /// If \p ShouldRenumberMetadata, renumber metadata for canonical assembly
+  /// output before printing.
   LLVM_ABI PrintModulePass(raw_ostream &OS, const std::string &Banner = "",
                            bool ShouldPreserveUseListOrder = false,
-                           bool EmitSummaryIndex = false);
-
+                           bool EmitSummaryIndex = false,
+                           bool ShouldRenumberMetadata = false);
   LLVM_ABI PreservedAnalyses run(Module &M, AnalysisManager<Module> &);
 };
 
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index a9caf95a32ef9..ef4927e2c4ee3 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -360,7 +360,7 @@ static void mapValueToSlot(const Value *V, ModuleSlotTracker &MST,
 /// Creates the mapping from slot numbers to function's unnamed IR values.
 static void initSlots2Values(const Function &F,
                              DenseMap<unsigned, const Value *> &Slots2Values) {
-  ModuleSlotTracker MST(F.getParent(), /*ShouldInitializeAllMetadata=*/false);
+  ModuleSlotTracker MST(F.getParent());
   MST.incorporateFunction(F);
   for (const auto &Arg : F.args())
     mapValueToSlot(&Arg, MST, Slots2Values);
@@ -3813,7 +3813,7 @@ bool MIParser::parseMMRA(MDNode *&Node) {
 static void initSlots2BasicBlocks(
     const Function &F,
     DenseMap<unsigned, const BasicBlock *> &Slots2BasicBlocks) {
-  ModuleSlotTracker MST(F.getParent(), /*ShouldInitializeAllMetadata=*/false);
+  ModuleSlotTracker MST(F.getParent());
   MST.incorporateFunction(F);
   for (const auto &BB : F) {
     if (BB.hasName())
diff --git a/llvm/lib/CodeGen/MIRPrintingPass.cpp b/llvm/lib/CodeGen/MIRPrintingPass.cpp
index f5e455a520151..5f6537cdd8c13 100644
--- a/llvm/lib/CodeGen/MIRPrintingPass.cpp
+++ b/llvm/lib/CodeGen/MIRPrintingPass.cpp
@@ -12,16 +12,20 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/MIRPrinter.h"
+#include "llvm/CodeGen/MachineFunctionAnalysis.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineModuleSlotTracker.h"
 #include "llvm/CodeGen/Passes.h"
 #include "llvm/CodeGen/VirtRegMap.h"
 #include "llvm/IR/Function.h"
+#include "llvm/IR/Module.h"
 #include "llvm/InitializePasses.h"
 
 using namespace llvm;
 
 PreservedAnalyses PrintMIRPreparePass::run(Module &M, ModuleAnalysisManager &) {
+  M.renumberMetadataForAssembly();
   printMIR(OS, M);
   return PreservedAnalyses::all();
 }
@@ -32,6 +36,14 @@ PreservedAnalyses PrintMIRPass::run(MachineFunction &MF,
                   .getManager();
 
   const VirtRegMap *VRM = MFAM.getCachedResult<VirtRegMapAnalysis>(MF);
+  MachineModuleSlotTracker MST(
+      [&](const Function &F) {
+        return &FAM.getResult<MachineFunctionAnalysis>(
+                       const_cast<Function &>(F))
+                    .getMF();
+      },
+      &MF);
+  MST.renumberMetadataForAssembly();
   printMIR(OS, FAM, MF, VRM);
   return PreservedAnalyses::all();
 }
@@ -67,12 +79,16 @@ struct MIRPrintingPass : public MachineFunctionPass {
     if (auto *W = getAnalysisIfAvailable<VirtRegMapWrapperLegacy>())
       VRM = &W->getVRM();
 
+    MachineModuleSlotTracker MST(
+        [&](const Function &F) { return MMI->getMachineFunction(F); }, &MF);
+    MST.renumberMetadataForAssembly();
     printMIR(StrOS, *MMI, MF, VRM);
     MachineFunctions.append(Str);
     return false;
   }
 
   bool doFinalization(Module &M) override {
+    M.renumberMetadataForAssembly();
     printMIR(OS, M);
     OS << MachineFunctions;
     return false;
diff --git a/llvm/lib/CodeGen/MachineBasicBlock.cpp b/llvm/lib/CodeGen/MachineBasicBlock.cpp
index 08a67935b52f5..b58a11efd103c 100644
--- a/llvm/lib/CodeGen/MachineBasicBlock.cpp
+++ b/llvm/lib/CodeGen/MachineBasicBlock.cpp
@@ -503,7 +503,7 @@ void MachineBasicBlock::printName(raw_ostream &os, unsigned printNameFlags,
       if (moduleSlotTracker) {
         slot = moduleSlotTracker->getLocalSlot(bb);
       } else if (bb->getParent()) {
-        ModuleSlotTracker tmpTracker(bb->getModule(), false);
+        ModuleSlotTracker tmpTracker(bb->getModule());
         tmpTracker.incorporateFunction(*bb->getParent());
         slot = tmpTracker.getLocalSlot(bb);
       }
diff --git a/llvm/lib/CodeGen/MachineModuleSlotTracker.cpp b/llvm/lib/CodeGen/MachineModuleSlotTracker.cpp
index e08b03eb4d70c..9e7ea156eab69 100644
--- a/llvm/lib/CodeGen/MachineModuleSlotTracker.cpp
+++ b/llvm/lib/CodeGen/MachineModuleSlotTracker.cpp
@@ -16,92 +16,98 @@
 
 using namespace llvm;
 
-void MachineModuleSlotTracker::processMachineFunctionMetadata(
-    AbstractSlotTrackerStorage *AST, const MachineFunction &MF) {
-  // Create metadata created within the backend.
+bool MachineModuleSlotTracker::shouldPrintDebugLocationInline(
+    const DILocation *DL) const {
+  return InlineDebugLocations.contains(DL);
+}
+
+void MachineModuleSlotTracker::collectMachineFunctionMetadata(
+    SmallVectorImpl<const MDNode *> &Metadata, const MachineFunction &MF,
+    SmallVectorImpl<const MDNode *> *DebugLocations) const {
   for (const MachineBasicBlock &MBB : MF)
     for (const MachineInstr &MI : MBB.instrs()) {
+      if (DebugLocations)
+        if (DebugLoc DL = MI.getDebugLoc())
+          DebugLocations->push_back(DL.getAsMDNode());
+
       if (MDNode *N = MI.getHeapAllocMarker())
-        AST->createMetadataSlot(N);
+        Metadata.push_back(N);
       if (MDNode *N = MI.getPCSections())
-        AST->createMetadataSlot(N);
+        Metadata.push_back(N);
       if (MDNode *N = MI.getMMRAMetadata())
-        AST->createMetadataSlot(N);
+        Metadata.push_back(N);
 
       for (const MachineOperand &MO : MI.operands())
         if (MO.isMetadata())
-          AST->createMetadataSlot(MO.getMetadata());
+          Metadata.push_back(MO.getMetadata());
 
       for (const MachineMemOperand *MMO : MI.memoperands()) {
         AAMDNodes AAInfo = MMO->getAAInfo();
         if (AAInfo.TBAA)
-          AST->createMetadataSlot(AAInfo.TBAA);
+          Metadata.push_back(AAInfo.TBAA);
         if (AAInfo.TBAAStruct)
-          AST->createMetadataSlot(AAInfo.TBAAStruct);
+          Metadata.push_back(AAInfo.TBAAStruct);
         if (AAInfo.Scope)
-          AST->createMetadataSlot(AAInfo.Scope);
+          Metadata.push_back(AAInfo.Scope);
         if (AAInfo.NoAlias)
-          AST->createMetadataSlot(AAInfo.NoAlias);
+          Metadata.push_back(AAInfo.NoAlias);
         if (AAInfo.NoAliasAddrSpace)
-          AST->createMetadataSlot(AAInfo.NoAliasAddrSpace);
+          Metadata.push_back(AAInfo.NoAliasAddrSpace);
         if (const MDNode *N = MMO->getRanges())
-          AST->createMetadataSlot(N);
+          Metadata.push_back(N);
         if (const MDNode *N = MMO->getMemCacheHint())
-          AST->createMetadataSlot(N);
+          Metadata.push_back(N);
       }
     }
 
   for (const MachineFunction::VariableDbgInfo &DebugVar :
        MF.getVariableDbgInfo()) {
-    AST->createMetadataSlot(DebugVar.Var);
+    Metadata.push_back(DebugVar.Var);
+    if (DebugLocations)
+      DebugLocations->push_back(DebugVar.Loc);
   }
 }
 
-void MachineModuleSlotTracker::processMachineModule(
-    AbstractSlotTrackerStorage *AST, const Module *M,
-    bool ShouldInitializeAllMetadata) {
-  if (ShouldInitializeAllMetadata) {
-    for (const Function &F : *M) {
-      if (&F != &TheFunction)
-        continue;
-      MDNStartSlot = AST->getNextMetadataSlot();
-      if (TheMF)
-        processMachineFunctionMetadata(AST, *TheMF);
-      MDNEndSlot = AST->getNextMetadataSlot();
-      break;
-    }
-  }
+void MachineModuleSlotTracker::collectMachineMDNodes(
+    MachineMDNodeListType &L) const {
+  L.insert(L.end(), MachineMDNodes.begin(), MachineMDNodes.end());
 }
 
-void MachineModuleSlotTracker::processMachineFunction(
-    AbstractSlotTrackerStorage *AST, const Function *F,
-    bool ShouldInitializeAllMetadata) {
-  if (!ShouldInitializeAllMetadata && F == &TheFunction) {
-    MDNStartSlot = AST->getNextMetadataSlot();
-    if (TheMF)
-      processMachineFunctionMetadata(AST, *TheMF);
-    MDNEndSlot = AST->getNextMetadataSlot();
-  }
-}
+void MachineModuleSlotTracker::renumberMetadataForAssembly() {
+  if (!TheMF)
+    return;
 
-void MachineModuleSlotTracker::collectMachineMDNodes(
-    MachineMDNodeListType &L) const {
-  collectMDNodes(L, MDNStartSlot, MDNEndSlot);
+  SmallVector<const MDNode *, 16> Metadata;
+  collectMachineFunctionMetadata(Metadata, *TheMF);
+  MachineMDNodes.clear();
+  ModuleSlotTracker::renumberMetadataForAssembly(Metadata, &MachineMDNodes);
 }
 
-MachineModuleSlotTracker::MachineModuleSlotTracker(
-    MFGetterFnT Fn, const MachineFunction *MF, bool ShouldInitializeAllMetadata)
-    : ModuleSlotTracker(MF->getFunction().getParent(),
-                        ShouldInitializeAllMetadata),
-      TheFunction(MF->getFunction()), TheMF(Fn(MF->getFunction())) {
-  setProcessHook([this](AbstractSlotTrackerStorage *AST, const Module *M,
-                        bool ShouldInitializeAllMetadata) {
-    this->processMachineModule(AST, M, ShouldInitializeAllMetadata);
-  });
-  setProcessHook([this](AbstractSlotTrackerStorage *AST, const Function *F,
-                        bool ShouldInitializeAllMetadata) {
-    this->processMachineFunction(AST, F, ShouldInitializeAllMetadata);
-  });
+MachineModuleSlotTracker::MachineModuleSlotTracker(MFGetterFnT Fn,
+                                                   const MachineFunction *MF)
+    : ModuleSlotTracker(MF->getFunction().getParent()),
+      TheMF(Fn(MF->getFunction())) {
+  if (!TheMF)
+    return;
+
+  SmallVector<const MDNode *, 16> Metadata;
+  SmallVector<const MDNode *, 16> DebugLocations;
+  collectMachineFunctionMetadata(Metadata, *TheMF, &DebugLocations);
+  collectAdditionalMetadata(Metadata, MachineMDNodes);
+
+  if (DebugLocations.empty())
+    return;
+
+  MachineMDNodeListType DebugMetadataNodes;
+  collectAdditionalMetadata(DebugLocations, DebugMetadataNodes);
+  SmallPtrSet<const MDNode *, 16> MachineMetadata;
+  for (const auto &Entry : MachineMDNodes)
+    MachineMetadata.insert(Entry.second);
+
+  for (const auto &Entry : DebugMetadataNodes)
+    if (isa<DILocation>(Entry.second) &&
+        !MachineMetadata.contains(Entry.second))
+      InlineDebugLocations.insert(cast<DILocation>(Entry.second));
 }
 
 MachineModuleSlotTracker::~MachineModuleSlotTracker() = default;
diff --git a/llvm/lib/CodeGen/MachineOperand.cpp b/llvm/lib/CodeGen/MachineOperand.cpp
index 3067f6e636130..af1487038de59 100644
--- a/llvm/lib/CodeGen/MachineOperand.cpp
+++ b/llvm/lib/CodeGen/MachineOperand.cpp
@@ -529,7 +529,7 @@ static void printIRBlockReference(raw_ostream &OS, const BasicBlock &BB,
     if (F == MST.getCurrentFunction()) {
       Slot = MST.getLocalSlot(&BB);
     } else if (const Module *M = F->getParent()) {
-      ModuleSlotTracker CustomMST(M, /*ShouldInitializeAllMetadata=*/false);
+      ModuleSlotTracker CustomMST(M);
       CustomMST.incorporateFunction(*F);
       Slot = CustomMST.getLocalSlot(&BB);
     }
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index f23a4b0bcc29d..8c1d4fa6c13cd 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -15,11 +15,13 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "LLVMContextImpl.h"
 #include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallString.h"
@@ -798,11 +800,11 @@ class llvm::SlotTracker : public AbstractSlotTrackerStorage {
   /// TheFunction - The function for which we are holding slot numbers.
   const Function* TheFunction = nullptr;
   bool FunctionProcessed = false;
-  bool ShouldInitializeAllMetadata;
+  bool ShouldTrackMetadataDefinitions;
 
-  std::function<void(AbstractSlotTrackerStorage *, const Module *, bool)>
+  std::function<void(AbstractSlotTrackerStorage *, const Module *)>
       ProcessModuleHookFn;
-  std::function<void(AbstractSlotTrackerStorage *, const Function *, bool)>
+  std::function<void(AbstractSlotTrackerStorage *, const Function *)>
       ProcessFunctionHookFn;
 
   /// The summary index for which we are holding slot numbers.
@@ -818,8 +820,6 @@ class llvm::SlotTracker : public AbstractSlotTrackerStorage {
 
   /// mdnMap - Map for MDNodes.
   DenseMap<const MDNode *, unsigned> mdnMap;
-  unsigned mdnNext = 0;
-
   /// asMap - The slot map for attribute sets.
   DenseMap<AttributeSet, unsigned> asMap;
   unsigned asNext = 0;
@@ -844,19 +844,12 @@ class llvm::SlotTracker : public AbstractSlotTrackerStorage {
 public:
   /// Construct from a module.
   ///
-  /// If \c ShouldInitializeAllMetadata, initializes all metadata in all
-  /// functions, giving correct numbering for metadata referenced only from
-  /// within a function (even if no functions have been initialized).
   explicit SlotTracker(const Module *M,
-                       bool ShouldInitializeAllMetadata = false);
+                       bool ShouldTrackMetadataDefinitions = false);
 
   /// Construct from a function, starting out in incorp state.
   ///
-  /// If \c ShouldInitializeAllMetadata, initializes all metadata in all
-  /// functions, giving correct numbering for metadata referenced only from
-  /// within a function (even if no functions have been initialized).
-  explicit SlotTracker(const Function *F,
-                       bool ShouldInitializeAllMetadata = false);
+  explicit SlotTracker(const Function *F);
 
   /// Construct from a module summary index.
   explicit SlotTracker(const ModuleSummaryIndex *Index);
@@ -867,11 +860,9 @@ class llvm::SlotTracker : public AbstractSlotTrackerStorage {
   ~SlotTracker() override = default;
 
   void setProcessHook(
-      std::function<void(AbstractSlotTrackerStorage *, const Module *, bool)>);
-  void setProcessHook(std::function<void(AbstractSlotTrackerStorage *,
-                                         const Function *, bool)>);
-
-  unsigned getNextMetadataSlot() override { return mdnNext; }
+      std::function<void(AbstractSlotTrackerStorage *, const Module *)>);
+  void setProcessHook(
+      std::function<void(AbstractSlotTrackerStorage *, const Function *)>);
 
   void createMetadataSlot(const MDNode *N) override;
 
@@ -928,7 +919,7 @@ class llvm::SlotTracker : public AbstractSlotTrackerStorage {
   /// CreateModuleSlot - Insert the specified GlobalValue* into the slot table.
   void CreateModuleSlot(const GlobalValue *V);
 
-  /// CreateMetadataSlot - Insert the specified MDNode* into the slot table.
+  /// Record a metadata definition and the metadata nodes referenced by it.
   void CreateMetadataSlot(const MDNode *N);
 
   /// CreateFunctionSlot - Insert the specified Value* into the slot table.
@@ -950,28 +941,14 @@ class llvm::SlotTracker : public AbstractSlotTrackerStorage {
 
   /// Add all of the functions arguments, basic blocks, and instructions.
   void processFunction();
-
-  /// Add the metadata directly attached to a GlobalObject.
-  void processGlobalObjectMetadata(const GlobalObject &GO);
-
-  /// Add all of the metadata from a function.
-  void processFunctionMetadata(const Function &F);
-
-  /// Add all of the metadata from an instruction.
-  void processInstructionMetadata(const Instruction &I);
-
-  /// Add all of the metadata from a DbgRecord.
-  void processDbgRecordMetadata(const DbgRecord &DVR);
 };
 
 ModuleSlotTracker::ModuleSlotTracker(SlotTracker &Machine, const Module *M,
                                      const Function *F)
     : M(M), F(F), Machine(&Machine) {}
 
-ModuleSlotTracker::ModuleSlotTracker(const Module *M,
-                                     bool ShouldInitializeAllMetadata)
-    : ShouldCreateStorage(M),
-      ShouldInitializeAllMetadata(ShouldInitializeAllMetadata), M(M) {}
+ModuleSlotTracker::ModuleSlotTracker(const Module *M)
+    : ShouldCreateStorage(M), M(M) {}
 
 ModuleSlotTracker::~ModuleSlotTracker() = default;
 
@@ -980,8 +957,7 @@ SlotTracker *ModuleSlotTracker::getMachine() {
     return Machine;
 
   ShouldCreateStorage = false;
-  MachineStorage =
-      std::make_unique<SlotTracker>(M, ShouldInitializeAllMetadata);
+  MachineStorage = std::make_unique<SlotTracker>(M);
   Machine = MachineStorage.get();
   if (ProcessModuleHookFn)
     Machine->setProcessHook(ProcessModuleHookFn);
@@ -1010,14 +986,12 @@ int ModuleSlotTracker::getLocalSlot(const Value *V) {
 }
 
 void ModuleSlotTracker::setProcessHook(
-    std::function<void(AbstractSlotTrackerStorage *, const Module *, bool)>
-        Fn) {
+    std::function<void(AbstractSlotTrackerStorage *, const Module *)> Fn) {
   ProcessModuleHookFn = std::move(Fn);
 }
 
 void ModuleSlotTracker::setProcessHook(
-    std::function<void(AbstractSlotTrackerStorage *, const Function *, bool)>
-        Fn) {
+    std::function<void(AbstractSlotTrackerStorage *, const Function *)> Fn) {
   ProcessFunctionHookFn = std::move(Fn);
 }
 
@@ -1055,17 +1029,19 @@ static SlotTracker *createSlotTracker(const Value *V) {
 
 // Module level constructor. Causes the contents of the Module (sans functions)
 // to be added to the slot table.
-SlotTracker::SlotTracker(const Module *M, bool ShouldInitializeAllMetadata)
-    : TheModule(M), ShouldInitializeAllMetadata(ShouldInitializeAllMetadata) {}
+SlotTracker::SlotTracker(const Module *M, bool ShouldTrackMetadataDefinitions)
+    : TheModule(M),
+      ShouldTrackMetadataDefinitions(ShouldTrackMetadataDefinitions) {}
 
 // Function level constructor. Causes the contents of the Module and the one
 // function provided to be added to the slot table.
-SlotTracker::SlotTracker(const Function *F, bool ShouldInitializeAllMetadata)
+SlotTracker::SlotTracker(const Function *F)
     : TheModule(F ? F->getParent() : nullptr), TheFunction(F),
-      ShouldInitializeAllMetadata(ShouldInitializeAllMetadata) {}
+      ShouldTrackMetadataDefinitions(false) {}
 
 SlotTracker::SlotTracker(const ModuleSummaryIndex *Index)
-    : TheModule(nullptr), ShouldInitializeAllMetadata(false), TheIndex(Index) {}
+    : TheModule(nullptr), ShouldTrackMetadataDefinitions(false),
+      TheIndex(Index) {}
 
 inline void SlotTracker::initializeIfNeeded() {
   if (TheModule) {
@@ -1094,7 +1070,6 @@ void SlotTracker::processModule() {
   for (const GlobalVariable &Var : TheModule->globals()) {
     if (!Var.hasName())
       CreateModuleSlot(&Var);
-    processGlobalObjectMetadata(Var);
     auto Attrs = Var.getAttributes();
     if (Attrs.hasAttributes())
       CreateAttributeSetSlot(Attrs);
@@ -1108,13 +1083,6 @@ void SlotTracker::processModule() {
   for (const GlobalIFunc &I : TheModule->ifuncs()) {
     if (!I.hasName())
       CreateModuleSlot(&I);
-    processGlobalObjectMetadata(I);
-  }
-
-  // Add metadata used by named metadata.
-  for (const NamedMDNode &NMD : TheModule->named_metadata()) {
-    for (const MDNode *N : NMD.operands())
-      CreateMetadataSlot(N);
   }
 
   for (const Function &F : *TheModule) {
@@ -1122,9 +1090,6 @@ void SlotTracker::processModule() {
       // Add all the unnamed functions to the table.
       CreateModuleSlot(&F);
 
-    if (ShouldInitializeAllMetadata)
-      processFunctionMetadata(F);
-
     // Add all the function attributes to the table.
     // FIXME: Add attributes of other objects?
     AttributeSet FnAttrs = F.getAttributes().getFnAttrs();
@@ -1133,7 +1098,7 @@ void SlotTracker::processModule() {
   }
 
   if (ProcessModuleHookFn)
-    ProcessModuleHookFn(this, TheModule, ShouldInitializeAllMetadata);
+    ProcessModuleHookFn(this, TheModule);
 
   ST_DEBUG("end processModule!\n");
 }
@@ -1143,10 +1108,6 @@ void SlotTracker::processFunction() {
   ST_DEBUG("begin processFunction!\n");
   fNext = 0;
 
-  // Process function metadata if it wasn't hit at the module-level.
-  if (!ShouldInitializeAllMetadata)
-    processFunctionMetadata(*TheFunction);
-
   // Add all the function arguments with no names.
   for(Function::const_arg_iterator AI = TheFunction->arg_begin(),
       AE = TheFunction->arg_end(); AI != AE; ++AI)
@@ -1176,7 +1137,7 @@ void SlotTracker::processFunction() {
   }
 
   if (ProcessFunctionHookFn)
-    ProcessFunctionHookFn(this, TheFunction, ShouldInitializeAllMetadata);
+    ProcessFunctionHookFn(this, TheFunction);
 
   FunctionProcessed = true;
 
@@ -1219,68 +1180,168 @@ int SlotTracker::processIndex() {
   return TypeIdNext;
 }
 
-void SlotTracker::processGlobalObjectMetadata(const GlobalObject &GO) {
-  SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
-  GO.getAllMetadata(MDs);
-  for (auto &MD : MDs)
-    CreateMetadataSlot(MD.second);
-}
+namespace {
+class MetadataNodeVisitor {
+  /// Visited MDNodes.
+  SmallPtrSet<const MDNode *, 32> VisitedMDNodes;
+  function_ref<void(const MDNode *)> Visit;
 
-void SlotTracker::processFunctionMetadata(const Function &F) {
-  processGlobalObjectMetadata(F);
-  for (auto &BB : F) {
-    for (auto &I : BB) {
-      for (const DbgRecord &DR : I.getDbgRecordRange())
-        processDbgRecordMetadata(DR);
-      processInstructionMetadata(I);
-    }
+  void visit(const MDNode *N) {
+    if (isa<DIExpression>(N) || !VisitedMDNodes.insert(N).second)
+      return;
+
+    Visit(N);
+    for (const MDOperand &Op : N->operands())
+      if (const auto *OpNode = dyn_cast_or_null<MDNode>(Op.get()))
+        visit(OpNode);
   }
-}
 
-void SlotTracker::processDbgRecordMetadata(const DbgRecord &DR) {
-  // Tolerate null metadata pointers: it's a completely illegal debug record,
-  // but we can have faulty metadata from debug-intrinsic days being
-  // autoupgraded into debug records. This gets caught by the verifier, which
-  // then will print the faulty IR, hitting this code path.
-  if (const auto *DVR = dyn_cast<const DbgVariableRecord>(&DR)) {
-    // Process metadata used by DbgRecords; we only specifically care about the
-    // DILocalVariable, DILocation, and DIAssignID fields, as the Value and
-    // Expression fields should only be printed inline and so do not use a slot.
-    // Note: The above doesn't apply for empty-metadata operands.
-    if (auto *Empty = dyn_cast_if_present<MDNode>(DVR->getRawLocation()))
-      CreateMetadataSlot(Empty);
-    if (DVR->getRawVariable())
-      CreateMetadataSlot(DVR->getRawVariable());
-    if (DVR->isDbgAssign()) {
-      if (auto *AssignID = DVR->getRawAssignID())
-        CreateMetadataSlot(cast<MDNode>(AssignID));
-      if (auto *Empty = dyn_cast_if_present<MDNode>(DVR->getRawAddress()))
-        CreateMetadataSlot(Empty);
+  void visitGlobalObjectMetadata(const GlobalObject &GO) {
+    SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
+    GO.getAllMetadata(MDs);
+    for (auto &MD : MDs)
+      visit(MD.second);
+  }
+
+  void visitDbgRecordMetadata(const DbgRecord &DR) {
+    if (const auto *DVR = dyn_cast<const DbgVariableRecord>(&DR)) {
+      if (auto *Empty = dyn_cast_if_present<MDNode>(DVR->getRawLocation()))
+        visit(Empty);
+      if (DVR->getRawVariable())
+        visit(DVR->getRawVariable());
+      if (DVR->isDbgAssign()) {
+        if (auto *AssignID = DVR->getRawAssignID())
+          visit(cast<MDNode>(AssignID));
+        if (auto *Empty = dyn_cast_if_present<MDNode>(DVR->getRawAddress()))
+          visit(Empty);
+      }
+    } else if (const auto *DLR = dyn_cast<const DbgLabelRecord>(&DR)) {
+      visit(DLR->getRawLabel());
+    } else {
+      llvm_unreachable("unsupported DbgRecord kind");
     }
-  } else if (const auto *DLR = dyn_cast<const DbgLabelRecord>(&DR)) {
-    CreateMetadataSlot(DLR->getRawLabel());
-  } else {
-    llvm_unreachable("unsupported DbgRecord kind");
+    if (DR.getDebugLoc())
+      visit(DR.getDebugLoc().getAsMDNode());
+  }
+
+  void visitInstructionMetadata(const Instruction &I) {
+    if (const auto *CI = dyn_cast<CallInst>(&I))
+      if (Function *F = CI->getCalledFunction())
+        if (F->isIntrinsic())
+          for (auto &Op : I.operands())
+            if (auto *V = dyn_cast_or_null<MetadataAsValue>(Op))
+              if (auto *N = dyn_cast<MDNode>(V->getMetadata()))
+                visit(N);
+
+    SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
+    I.getAllMetadata(MDs);
+    for (auto &MD : MDs)
+      visit(MD.second);
+  }
+
+  void visitFunctionMetadata(const Function &F) {
+    visitGlobalObjectMetadata(F);
+    for (const BasicBlock &BB : F)
+      for (const Instruction &I : BB) {
+        for (const DbgRecord &DR : I.getDbgRecordRange())
+          visitDbgRecordMetadata(DR);
+        visitInstructionMetadata(I);
+      }
+  }
+
+public:
+  MetadataNodeVisitor(function_ref<void(const MDNode *)> Visit)
+      : Visit(Visit) {}
+
+  void visitModuleMetadata(const Module &M) {
+    for (const GlobalVariable &Var : M.globals())
+      visitGlobalObjectMetadata(Var);
+    for (const GlobalIFunc &I : M.ifuncs())
+      visitGlobalObjectMetadata(I);
+    for (const NamedMDNode &NMD : M.named_metadata())
+      for (const MDNode *N : NMD.operands())
+        visit(N);
+    for (const Function &F : M)
+      visitFunctionMetadata(F);
+  }
+
+  void visitMetadata(ArrayRef<const MDNode *> Metadata) {
+    for (const MDNode *N : Metadata)
+      visit(N);
+  }
+
+  bool contains(const MDNode *N) const { return VisitedMDNodes.contains(N); }
+};
+
+class MetadataIDRenumberer {
+  uint32_t NextID = 0;
+
+public:
+  void run(const Module &M, ArrayRef<const MDNode *> AdditionalMetadata,
+           ModuleSlotTracker::MachineMDNodeListType *AdditionalMetadataNodes =
+               nullptr) {
+    bool IsAdditionalMetadata = false;
+    auto Renumber = [&](const MDNode *N) {
+      N->getContext().pImpl->setMetadataPrintID(const_cast<MDNode *>(N),
+                                                NextID++);
+      if (IsAdditionalMetadata && AdditionalMetadataNodes)
+        AdditionalMetadataNodes->emplace_back(
+            N->getContext().pImpl->getMetadataPrintID(N), N);
+    };
+    MetadataNodeVisitor Visitor(Renumber);
+
+    Visitor.visitModuleMetadata(M);
+
+    IsAdditionalMetadata = true;
+    Visitor.visitMetadata(AdditionalMetadata);
+
+    // Keep IDs unique for nodes outside the canonical output.
+    SmallVector<MDNode *, 32> RemainingNodes;
+    M.getContext().pImpl->getAllMetadataNodes(RemainingNodes);
+    llvm::erase_if(RemainingNodes, [&](const MDNode *N) {
+      return Visitor.contains(N) ||
+             M.getContext().pImpl->getMetadataPrintID(N) >= NextID;
+    });
+    llvm::sort(RemainingNodes, [&](const MDNode *LHS, const MDNode *RHS) {
+      return M.getContext().pImpl->getMetadataPrintID(LHS) <
+             M.getContext().pImpl->getMetadataPrintID(RHS);
+    });
+    for (MDNode *N : RemainingNodes)
+      M.getContext().pImpl->setMetadataPrintID(
+          N, M.getContext().pImpl->allocateMetadataPrintID());
+
+    if (AdditionalMetadataNodes)
+      llvm::sort(*AdditionalMetadataNodes);
   }
-  if (DR.getDebugLoc())
-    CreateMetadataSlot(DR.getDebugLoc().getAsMDNode());
+};
+} // namespace
+
+void Module::renumberMetadataForAssembly() {
+  MetadataIDRenumberer().run(*this, {});
 }
 
-void SlotTracker::processInstructionMetadata(const Instruction &I) {
-  // Process metadata used directly by intrinsics.
-  if (const auto *CI = dyn_cast<CallInst>(&I))
-    if (Function *F = CI->getCalledFunction())
-      if (F->isIntrinsic())
-        for (auto &Op : I.operands())
-          if (auto *V = dyn_cast_or_null<MetadataAsValue>(Op))
-            if (auto *N = dyn_cast<MDNode>(V->getMetadata()))
-              CreateMetadataSlot(N);
+void ModuleSlotTracker::renumberMetadataForAssembly(
+    ArrayRef<const MDNode *> AdditionalMetadata,
+    MachineMDNodeListType *AdditionalMetadataNodes) const {
+  assert(M && "metadata renumbering requires a module");
+  MetadataIDRenumberer().run(*M, AdditionalMetadata, AdditionalMetadataNodes);
+}
 
-  // Process metadata attached to this instruction.
-  SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
-  I.getAllMetadata(MDs);
-  for (auto &MD : MDs)
-    CreateMetadataSlot(MD.second);
+void ModuleSlotTracker::collectAdditionalMetadata(
+    ArrayRef<const MDNode *> AdditionalMetadata,
+    MachineMDNodeListType &AdditionalMetadataNodes) const {
+  assert(M && "metadata collection requires a module");
+  bool IsAdditionalMetadata = false;
+  auto Collect = [&](const MDNode *N) {
+    if (IsAdditionalMetadata)
+      AdditionalMetadataNodes.emplace_back(
+          N->getContext().pImpl->getMetadataPrintID(N), N);
+  };
+  MetadataNodeVisitor Visitor(Collect);
+  Visitor.visitModuleMetadata(*M);
+  IsAdditionalMetadata = true;
+  Visitor.visitMetadata(AdditionalMetadata);
+  llvm::sort(AdditionalMetadataNodes);
 }
 
 /// Clean up after incorporating a function. This is the only way to get out of
@@ -1305,14 +1366,12 @@ int SlotTracker::getGlobalSlot(const GlobalValue *V) {
 }
 
 void SlotTracker::setProcessHook(
-    std::function<void(AbstractSlotTrackerStorage *, const Module *, bool)>
-        Fn) {
+    std::function<void(AbstractSlotTrackerStorage *, const Module *)> Fn) {
   ProcessModuleHookFn = std::move(Fn);
 }
 
 void SlotTracker::setProcessHook(
-    std::function<void(AbstractSlotTrackerStorage *, const Function *, bool)>
-        Fn) {
+    std::function<void(AbstractSlotTrackerStorage *, const Function *)> Fn) {
   ProcessFunctionHookFn = std::move(Fn);
 }
 
@@ -1324,9 +1383,11 @@ int SlotTracker::getMetadataSlot(const MDNode *N) {
   // Check for uninitialized state and do lazy initialization.
   initializeIfNeeded();
 
-  // Find the MDNode in the module map
-  mdn_iterator MI = mdnMap.find(N);
-  return MI == mdnMap.end() ? -1 : (int)MI->second;
+  if (isa<DIExpression>(N))
+    return -1;
+  if (ShouldTrackMetadataDefinitions)
+    CreateMetadataSlot(N);
+  return N->getContext().pImpl->getMetadataPrintID(N);
 }
 
 /// getLocalSlot - Get the slot number for a value that is local to a function.
@@ -1419,19 +1480,16 @@ void SlotTracker::CreateFunctionSlot(const Value *V) {
 void SlotTracker::CreateMetadataSlot(const MDNode *N) {
   assert(N && "Can't insert a null Value into SlotTracker!");
 
-  // Don't make slots for DIExpressions. We just print them inline everywhere.
   if (isa<DIExpression>(N))
     return;
 
-  unsigned DestSlot = mdnNext;
-  if (!mdnMap.insert(std::make_pair(N, DestSlot)).second)
+  unsigned ID = N->getContext().pImpl->getMetadataPrintID(N);
+  if (!mdnMap.try_emplace(N, ID).second)
     return;
-  ++mdnNext;
 
-  // Recursively add any MDNodes referenced by operands.
-  for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
-    if (const auto *Op = dyn_cast_or_null<MDNode>(N->getOperand(i)))
-      CreateMetadataSlot(Op);
+  for (const MDOperand &Op : N->operands())
+    if (const auto *OpNode = dyn_cast_or_null<MDNode>(Op.get()))
+      CreateMetadataSlot(OpNode);
 }
 
 void SlotTracker::CreateAttributeSetSlot(AttributeSet AS) {
@@ -1467,9 +1525,11 @@ struct AsmWriterContext {
   TypePrinting *TypePrinter = nullptr;
   SlotTracker *Machine = nullptr;
   const Module *Context = nullptr;
+  const ModuleSlotTracker *MST = nullptr;
 
-  AsmWriterContext(TypePrinting *TP, SlotTracker *ST, const Module *M = nullptr)
-      : TypePrinter(TP), Machine(ST), Context(M) {}
+  AsmWriterContext(TypePrinting *TP, SlotTracker *ST, const Module *M = nullptr,
+                   const ModuleSlotTracker *MST = nullptr)
+      : TypePrinter(TP), Machine(ST), Context(M), MST(MST) {}
 
   static AsmWriterContext &getEmpty() {
     static AsmWriterContext EmptyCtx(nullptr, nullptr);
@@ -2845,6 +2905,13 @@ static void writeAsOperandInternal(raw_ostream &Out, const Metadata *MD,
   }
 
   if (const auto *N = dyn_cast<MDNode>(MD)) {
+    if (const auto *Loc = dyn_cast<DILocation>(N);
+        Loc && WriterCtx.MST &&
+        WriterCtx.MST->shouldPrintDebugLocationInline(Loc)) {
+      writeDILocation(Out, Loc, WriterCtx);
+      return;
+    }
+
     std::unique_ptr<SlotTracker> MachineStorage;
     SaveAndRestore SARMachine(WriterCtx.Machine);
     if (!WriterCtx.Machine) {
@@ -5032,14 +5099,14 @@ void AssemblyWriter::writeMDNode(unsigned Slot, const MDNode *Node) {
 }
 
 void AssemblyWriter::writeAllMDNodes() {
-  SmallVector<const MDNode *, 16> Nodes;
-  Nodes.resize(Machine.mdn_size());
+  SmallVector<std::pair<unsigned, const MDNode *>, 16> Nodes;
+  Nodes.reserve(Machine.mdn_size());
   for (auto &I : llvm::make_range(Machine.mdn_begin(), Machine.mdn_end()))
-    Nodes[I.second] = cast<MDNode>(I.first);
+    Nodes.emplace_back(I.second, cast<MDNode>(I.first));
+  llvm::sort(Nodes);
 
-  for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
-    writeMDNode(i, Nodes[i]);
-  }
+  for (auto [Slot, Node] : Nodes)
+    writeMDNode(Slot, Node);
 }
 
 void AssemblyWriter::printMDNodeBody(const MDNode *Node) {
@@ -5110,7 +5177,7 @@ void AssemblyWriter::printUseLists(const Function *F) {
 
 void Function::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW,
                      bool ShouldPreserveUseListOrder, bool IsForDebug) const {
-  SlotTracker SlotTable(this->getParent());
+  SlotTracker SlotTable(this);
   formatted_raw_ostream OS(ROS);
   AssemblyWriter W(OS, SlotTable, this->getParent(), AAW, IsForDebug,
                    ShouldPreserveUseListOrder);
@@ -5129,7 +5196,7 @@ void BasicBlock::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW,
 
 void Module::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW,
                    bool ShouldPreserveUseListOrder, bool IsForDebug) const {
-  SlotTracker SlotTable(this);
+  SlotTracker SlotTable(this, /*ShouldTrackMetadataDefinitions=*/true);
   formatted_raw_ostream OS(ROS);
   AssemblyWriter W(OS, SlotTable, this, AAW, IsForDebug,
                    ShouldPreserveUseListOrder);
@@ -5199,26 +5266,15 @@ void Type::print(raw_ostream &OS, bool /*IsForDebug*/, bool NoDetails) const {
     }
 }
 
-static bool isReferencingMDNode(const Instruction &I) {
-  if (const auto *CI = dyn_cast<CallInst>(&I))
-    if (Function *F = CI->getCalledFunction())
-      if (F->isIntrinsic())
-        for (auto &Op : I.operands())
-          if (auto *V = dyn_cast_or_null<MetadataAsValue>(Op))
-            if (isa<MDNode>(V->getMetadata()))
-              return true;
-  return false;
-}
-
 void DbgMarker::print(raw_ostream &ROS, bool IsForDebug) const {
 
-  ModuleSlotTracker MST(getModuleFromDPI(this), true);
+  ModuleSlotTracker MST(getModuleFromDPI(this));
   print(ROS, MST, IsForDebug);
 }
 
 void DbgVariableRecord::print(raw_ostream &ROS, bool IsForDebug) const {
 
-  ModuleSlotTracker MST(getModuleFromDPI(this), true);
+  ModuleSlotTracker MST(getModuleFromDPI(this));
   print(ROS, MST, IsForDebug);
 }
 
@@ -5237,7 +5293,7 @@ void DbgMarker::print(raw_ostream &ROS, ModuleSlotTracker &MST,
 
 void DbgLabelRecord::print(raw_ostream &ROS, bool IsForDebug) const {
 
-  ModuleSlotTracker MST(getModuleFromDPI(this), true);
+  ModuleSlotTracker MST(getModuleFromDPI(this));
   print(ROS, MST, IsForDebug);
 }
 
@@ -5272,13 +5328,16 @@ void DbgLabelRecord::print(raw_ostream &ROS, ModuleSlotTracker &MST,
 }
 
 void Value::print(raw_ostream &ROS, bool IsForDebug) const {
-  bool ShouldInitializeAllMetadata = false;
-  if (auto *I = dyn_cast<Instruction>(this))
-    ShouldInitializeAllMetadata = isReferencingMDNode(*I);
-  else if (isa<Function>(this) || isa<MetadataAsValue>(this))
-    ShouldInitializeAllMetadata = true;
+  if (const auto *F = dyn_cast<Function>(this)) {
+    F->print(ROS, nullptr, /*ShouldPreserveUseListOrder=*/false, IsForDebug);
+    return;
+  }
+  if (const auto *BB = dyn_cast<BasicBlock>(this)) {
+    BB->print(ROS, nullptr, /*ShouldPreserveUseListOrder=*/false, IsForDebug);
+    return;
+  }
 
-  ModuleSlotTracker MST(getModuleFromVal(this), ShouldInitializeAllMetadata);
+  ModuleSlotTracker MST(getModuleFromVal(this));
   print(ROS, MST, IsForDebug);
 }
 
@@ -5358,8 +5417,7 @@ void Value::printAsOperand(raw_ostream &O, bool PrintType,
     if (printWithoutType(*this, O, nullptr, M))
       return;
 
-  SlotTracker Machine(
-      M, /* ShouldInitializeAllMetadata */ isa<MetadataAsValue>(this));
+  SlotTracker Machine(M);
   ModuleSlotTracker MST(Machine, M);
   printAsOperandImpl(*this, O, PrintType, MST);
 }
@@ -5400,8 +5458,10 @@ struct MDTreeAsmWriterContext : public AsmWriterContext {
   raw_ostream &MainOS;
 
   MDTreeAsmWriterContext(TypePrinting *TP, SlotTracker *ST, const Module *M,
-                         raw_ostream &OS, const Metadata *InitMD)
-      : AsmWriterContext(TP, ST, M), Level(0U), Visited({InitMD}), MainOS(OS) {}
+                         const ModuleSlotTracker *MST, raw_ostream &OS,
+                         const Metadata *InitMD)
+      : AsmWriterContext(TP, ST, M, MST), Level(0U), Visited({InitMD}),
+        MainOS(OS) {}
 
   void onWriteMetadataAsOperand(const Metadata *MD) override {
     if (!Visited.insert(MD).second)
@@ -5440,10 +5500,10 @@ static void printMetadataImpl(raw_ostream &ROS, const Metadata &MD,
   std::unique_ptr<AsmWriterContext> WriterCtx;
   if (PrintAsTree && !OnlyAsOperand)
     WriterCtx = std::make_unique<MDTreeAsmWriterContext>(
-        &TypePrinter, MST.getMachine(), M, OS, &MD);
+        &TypePrinter, MST.getMachine(), M, &MST, OS, &MD);
   else
-    WriterCtx =
-        std::make_unique<AsmWriterContext>(&TypePrinter, MST.getMachine(), M);
+    WriterCtx = std::make_unique<AsmWriterContext>(&TypePrinter,
+                                                   MST.getMachine(), M, &MST);
 
   writeAsOperandInternal(OS, &MD, *WriterCtx, /* FromValue */ true);
 
@@ -5456,7 +5516,7 @@ static void printMetadataImpl(raw_ostream &ROS, const Metadata &MD,
 }
 
 void Metadata::printAsOperand(raw_ostream &OS, const Module *M) const {
-  ModuleSlotTracker MST(M, isa<MDNode>(this));
+  ModuleSlotTracker MST(M);
   printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ true);
 }
 
@@ -5467,7 +5527,7 @@ void Metadata::printAsOperand(raw_ostream &OS, ModuleSlotTracker &MST,
 
 void Metadata::print(raw_ostream &OS, const Module *M,
                      bool /*IsForDebug*/) const {
-  ModuleSlotTracker MST(M, isa<MDNode>(this));
+  ModuleSlotTracker MST(M);
   printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ false);
 }
 
@@ -5477,7 +5537,7 @@ void Metadata::print(raw_ostream &OS, ModuleSlotTracker &MST,
 }
 
 void MDNode::printTree(raw_ostream &OS, const Module *M) const {
-  ModuleSlotTracker MST(M, true);
+  ModuleSlotTracker MST(M);
   printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ false,
                     /*PrintAsTree=*/true);
 }
@@ -5495,15 +5555,13 @@ void ModuleSummaryIndex::print(raw_ostream &ROS, bool IsForDebug) const {
   W.printModuleSummaryIndex();
 }
 
-void ModuleSlotTracker::collectMDNodes(MachineMDNodeListType &L, unsigned LB,
-                                       unsigned UB) const {
+void ModuleSlotTracker::collectMDNodes(MachineMDNodeListType &L) const {
   SlotTracker *ST = MachineStorage.get();
   if (!ST)
     return;
 
   for (auto &I : llvm::make_range(ST->mdn_begin(), ST->mdn_end()))
-    if (I.second >= LB && I.second < UB)
-      L.push_back(std::make_pair(I.second, I.first));
+    L.push_back(std::make_pair(I.second, I.first));
 }
 
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index a7abd3eed31c3..d1ee8411e392c 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -474,6 +474,7 @@ LLVMBool LLVMPrintModuleToFile(LLVMModuleRef M, const char *Filename,
     return true;
   }
 
+  unwrap(M)->renumberMetadataForAssembly();
   unwrap(M)->print(dest, nullptr);
 
   dest.close();
@@ -491,6 +492,7 @@ char *LLVMPrintModuleToString(LLVMModuleRef M) {
   std::string buf;
   raw_string_ostream os(buf);
 
+  unwrap(M)->renumberMetadataForAssembly();
   unwrap(M)->print(os, nullptr);
 
   return strdup(buf.c_str());
diff --git a/llvm/lib/IR/IRPrintingPasses.cpp b/llvm/lib/IR/IRPrintingPasses.cpp
index 43671b0b9a1a3..a84f8db98bee4 100644
--- a/llvm/lib/IR/IRPrintingPasses.cpp
+++ b/llvm/lib/IR/IRPrintingPasses.cpp
@@ -26,37 +26,49 @@ using namespace llvm;
 
 namespace {
 
+static void printModule(raw_ostream &OS, StringRef Banner,
+                        bool ShouldPreserveUseListOrder, Module &M) {
+  if (llvm::isFunctionInPrintList("*")) {
+    if (!Banner.empty())
+      OS << Banner << "\n";
+    M.print(OS, nullptr, ShouldPreserveUseListOrder);
+    return;
+  }
+
+  bool BannerPrinted = false;
+  for (const auto &F : M.functions()) {
+    if (!llvm::isFunctionInPrintList(F.getName()))
+      continue;
+    if (!BannerPrinted && !Banner.empty()) {
+      OS << Banner << "\n";
+      BannerPrinted = true;
+    }
+    F.print(OS);
+  }
+}
+
 class PrintModulePassWrapper : public ModulePass {
   raw_ostream &OS;
   std::string Banner;
   bool ShouldPreserveUseListOrder;
+  bool ShouldRenumberMetadata;
 
 public:
   static char ID;
-  PrintModulePassWrapper() : ModulePass(ID), OS(dbgs()) {}
+  PrintModulePassWrapper()
+      : ModulePass(ID), OS(dbgs()), ShouldPreserveUseListOrder(false),
+        ShouldRenumberMetadata(false) {}
   PrintModulePassWrapper(raw_ostream &OS, const std::string &Banner,
-                         bool ShouldPreserveUseListOrder)
+                         bool ShouldPreserveUseListOrder,
+                         bool ShouldRenumberMetadata)
       : ModulePass(ID), OS(OS), Banner(Banner),
-        ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) {}
+        ShouldPreserveUseListOrder(ShouldPreserveUseListOrder),
+        ShouldRenumberMetadata(ShouldRenumberMetadata) {}
 
   bool runOnModule(Module &M) override {
-    if (llvm::isFunctionInPrintList("*")) {
-      if (!Banner.empty())
-        OS << Banner << "\n";
-      M.print(OS, nullptr, ShouldPreserveUseListOrder);
-    } else {
-      bool BannerPrinted = false;
-      for (const auto &F : M.functions()) {
-        if (llvm::isFunctionInPrintList(F.getName())) {
-          if (!BannerPrinted && !Banner.empty()) {
-            OS << Banner << "\n";
-            BannerPrinted = true;
-          }
-          F.print(OS);
-        }
-      }
-    }
-
+    if (ShouldRenumberMetadata)
+      M.renumberMetadataForAssembly();
+    printModule(OS, Banner, ShouldPreserveUseListOrder, M);
     return false;
   }
 
@@ -80,10 +92,10 @@ class PrintFunctionPassWrapper : public FunctionPass {
   // This pass just prints a banner followed by the function as it's processed.
   bool runOnFunction(Function &F) override {
     if (isFunctionInPrintList(F.getName())) {
-      if (forcePrintModuleIR())
-        OS << Banner << " (function: " << F.getName() << ")\n"
-           << *F.getParent();
-      else
+      if (forcePrintModuleIR()) {
+        OS << Banner << " (function: " << F.getName() << ")\n";
+        F.getParent()->print(OS, nullptr);
+      } else
         OS << Banner << '\n' << static_cast<Value &>(F);
     }
 
@@ -109,7 +121,16 @@ INITIALIZE_PASS(PrintFunctionPassWrapper, "print-function",
 ModulePass *llvm::createPrintModulePass(llvm::raw_ostream &OS,
                                         const std::string &Banner,
                                         bool ShouldPreserveUseListOrder) {
-  return new PrintModulePassWrapper(OS, Banner, ShouldPreserveUseListOrder);
+  return createPrintModulePass(OS, Banner, ShouldPreserveUseListOrder,
+                               /*ShouldRenumberMetadata=*/false);
+}
+
+ModulePass *llvm::createPrintModulePass(llvm::raw_ostream &OS,
+                                        const std::string &Banner,
+                                        bool ShouldPreserveUseListOrder,
+                                        bool ShouldRenumberMetadata) {
+  return new PrintModulePassWrapper(OS, Banner, ShouldPreserveUseListOrder,
+                                    ShouldRenumberMetadata);
 }
 
 FunctionPass *llvm::createPrintFunctionPass(llvm::raw_ostream &OS,
diff --git a/llvm/lib/IR/LLVMContextImpl.cpp b/llvm/lib/IR/LLVMContextImpl.cpp
index 9d094cc6d1b72..5af5a477cf69a 100644
--- a/llvm/lib/IR/LLVMContextImpl.cpp
+++ b/llvm/lib/IR/LLVMContextImpl.cpp
@@ -38,6 +38,15 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C)
       Int64Ty(C, 64), Int128Ty(C, 128), Byte1Ty(C, 1), Byte8Ty(C, 8),
       Byte16Ty(C, 16), Byte32Ty(C, 32), Byte64Ty(C, 64), Byte128Ty(C, 128) {}
 
+void LLVMContextImpl::getAllMetadataNodes(
+    SmallVectorImpl<MDNode *> &Nodes) const {
+  Nodes.append(DistinctMDNodes.begin(), DistinctMDNodes.end());
+#define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS)                                    \
+  Nodes.append(CLASS##s.begin(), CLASS##s.end());
+#include "llvm/IR/Metadata.def"
+  Nodes.append(TemporaryMDNodes.begin(), TemporaryMDNodes.end());
+}
+
 LLVMContextImpl::~LLVMContextImpl() {
 #ifndef NDEBUG
   // Check that any variable location records that fell off the end of a block
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 2d22484d2ffb7..a6342389d8543 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -1637,6 +1637,20 @@ class LLVMContextImpl {
   DenseMap<Metadata *, MetadataAsValue *> MetadataAsValues;
   DenseSet<DIArgList *, DIArgListInfo> DIArgLists;
 
+  uint32_t NextMetadataPrintID = 0;
+
+  uint32_t allocateMetadataPrintID() { return NextMetadataPrintID++; }
+
+  void getAllMetadataNodes(SmallVectorImpl<MDNode *> &Nodes) const;
+
+  uint32_t getMetadataPrintID(const MDNode *N) const {
+    return N->getHeader().MetadataPrintID;
+  }
+
+  void setMetadataPrintID(MDNode *N, uint32_t ID) {
+    N->getHeader().MetadataPrintID = ID;
+  }
+
 #define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS)                                    \
   DenseSet<CLASS *, CLASS##Info> CLASS##s;
 #include "llvm/IR/Metadata.def"
@@ -1650,6 +1664,10 @@ class LLVMContextImpl {
   // them on context teardown.
   std::vector<MDNode *> DistinctMDNodes;
 
+  // Temporary nodes are caller-owned, but track live ones for persistent
+  // metadata print IDs.
+  DenseSet<MDNode *> TemporaryMDNodes;
+
   // ConstantRangeListAttributeImpl is a TrailingObjects/ArrayRef of
   // ConstantRange. Since this is a dynamically sized class, it's not
   // possible to use SpecificBumpPtrAllocator. Instead, we use normal Alloc
diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp
index 0a4141ee2362e..2b1a7bb117308 100644
--- a/llvm/lib/IR/Metadata.cpp
+++ b/llvm/lib/IR/Metadata.cpp
@@ -650,6 +650,8 @@ StringRef MDString::getString() const {
 void *MDNode::operator new(size_t Size, size_t NumOps, StorageType Storage) {
   // uint64_t is the most aligned type we need support (ensured by static_assert
   // above)
+  static_assert(sizeof(Header) == sizeof(size_t) + 2 * sizeof(uint32_t),
+                "MDNode header fields poorly packed");
   size_t AllocSize =
       alignTo(Header::getAllocSize(Storage, NumOps), alignof(uint64_t));
   char *Mem = reinterpret_cast<char *>(::operator new(AllocSize + Size));
@@ -667,6 +669,8 @@ void MDNode::operator delete(void *N) {
 MDNode::MDNode(LLVMContext &Context, unsigned ID, StorageType Storage,
                ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2)
     : Metadata(ID, Storage), Context(Context) {
+  getHeader().MetadataPrintID = Context.pImpl->allocateMetadataPrintID();
+
   unsigned Op = 0;
   for (Metadata *MD : Ops1)
     setOperand(Op++, MD);
@@ -781,6 +785,9 @@ void MDNode::countUnresolvedOperands() {
 void MDNode::makeUniqued() {
   assert(isTemporary() && "Expected this to be temporary");
   assert(!isResolved() && "Expected this to be unresolved");
+  bool WasTracked = getContext().pImpl->TemporaryMDNodes.erase(this);
+  assert(WasTracked && "Temporary node not tracked");
+  (void)WasTracked;
 
   // Enable uniquing callbacks.
   for (auto &Op : mutable_operands())
@@ -981,6 +988,11 @@ void MDNode::handleChangedOperand(void *Ref, Metadata *New) {
 }
 
 void MDNode::deleteAsSubclass() {
+  if (isTemporary()) {
+    bool WasTracked = getContext().pImpl->TemporaryMDNodes.erase(this);
+    assert(WasTracked && "Temporary node not tracked");
+    (void)WasTracked;
+  }
   switch (getMetadataID()) {
   default:
     llvm_unreachable("Invalid subclass of MDNode");
@@ -1066,6 +1078,11 @@ void MDNode::deleteTemporary(MDNode *N) {
 void MDNode::storeDistinctInContext() {
   assert(!Context.hasReplaceableUses() && "Unexpected replaceable uses");
   assert(!getNumUnresolved() && "Unexpected unresolved nodes");
+  if (isTemporary()) {
+    bool WasTracked = getContext().pImpl->TemporaryMDNodes.erase(this);
+    assert(WasTracked && "Temporary node not tracked");
+    (void)WasTracked;
+  }
   Storage = Distinct;
   assert(isResolved() && "Expected this to be resolved");
 
diff --git a/llvm/lib/IR/MetadataImpl.h b/llvm/lib/IR/MetadataImpl.h
index b4188dd7d3ee4..0045b7c406f97 100644
--- a/llvm/lib/IR/MetadataImpl.h
+++ b/llvm/lib/IR/MetadataImpl.h
@@ -33,6 +33,7 @@ template <class T> T *MDNode::storeImpl(T *N, StorageType Storage) {
     N->storeDistinctInContext();
     break;
   case Temporary:
+    N->getContext().pImpl->TemporaryMDNodes.insert(N);
     break;
   }
   return N;
@@ -48,6 +49,7 @@ T *MDNode::storeImpl(T *N, StorageType Storage, StoreT &Store) {
     N->storeDistinctInContext();
     break;
   case Temporary:
+    N->getContext().pImpl->TemporaryMDNodes.insert(N);
     break;
   }
   return N;
diff --git a/llvm/lib/IR/SSAContext.cpp b/llvm/lib/IR/SSAContext.cpp
index feb8570d32757..ca093a1e6a76c 100644
--- a/llvm/lib/IR/SSAContext.cpp
+++ b/llvm/lib/IR/SSAContext.cpp
@@ -93,7 +93,7 @@ template <> Printable SSAContext::print(const BasicBlock *BB) const {
     return Printable([BB](raw_ostream &Out) { Out << BB->getName(); });
 
   return Printable([BB](raw_ostream &Out) {
-    ModuleSlotTracker MST{BB->getParent()->getParent(), false};
+    ModuleSlotTracker MST{BB->getParent()->getParent()};
     MST.incorporateFunction(*BB->getParent());
     Out << MST.getLocalSlot(BB);
   });
diff --git a/llvm/lib/IRPrinter/IRPrintingPasses.cpp b/llvm/lib/IRPrinter/IRPrintingPasses.cpp
index adb192ac4a916..8893e34fdeec2 100644
--- a/llvm/lib/IRPrinter/IRPrintingPasses.cpp
+++ b/llvm/lib/IRPrinter/IRPrintingPasses.cpp
@@ -23,15 +23,22 @@
 
 using namespace llvm;
 
-PrintModulePass::PrintModulePass() : OS(dbgs()) {}
+PrintModulePass::PrintModulePass()
+    : OS(dbgs()), ShouldPreserveUseListOrder(false), EmitSummaryIndex(false),
+      ShouldRenumberMetadata(false) {}
 PrintModulePass::PrintModulePass(raw_ostream &OS, const std::string &Banner,
                                  bool ShouldPreserveUseListOrder,
-                                 bool EmitSummaryIndex)
+                                 bool EmitSummaryIndex,
+                                 bool ShouldRenumberMetadata)
     : OS(OS), Banner(Banner),
       ShouldPreserveUseListOrder(ShouldPreserveUseListOrder),
-      EmitSummaryIndex(EmitSummaryIndex) {}
+      EmitSummaryIndex(EmitSummaryIndex),
+      ShouldRenumberMetadata(ShouldRenumberMetadata) {}
 
 PreservedAnalyses PrintModulePass::run(Module &M, ModuleAnalysisManager &AM) {
+  if (ShouldRenumberMetadata)
+    M.renumberMetadataForAssembly();
+
   if (llvm::isFunctionInPrintList("*")) {
     if (!Banner.empty())
       OS << Banner << "\n";
@@ -68,9 +75,10 @@ PrintFunctionPass::PrintFunctionPass(raw_ostream &OS, const std::string &Banner)
 PreservedAnalyses PrintFunctionPass::run(Function &F,
                                          FunctionAnalysisManager &) {
   if (isFunctionInPrintList(F.getName())) {
-    if (forcePrintModuleIR())
-      OS << Banner << " (function: " << F.getName() << ")\n" << *F.getParent();
-    else
+    if (forcePrintModuleIR()) {
+      OS << Banner << " (function: " << F.getName() << ")\n";
+      F.getParent()->print(OS, nullptr);
+    } else
       OS << Banner << '\n' << static_cast<Value &>(F);
   }
 
diff --git a/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp b/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp
index 6f7d5f5f9c8a4..d6b55064a5850 100644
--- a/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp
+++ b/llvm/lib/Target/DirectX/DXILPrettyPrinter.cpp
@@ -9,6 +9,9 @@
 #include "DXILPrettyPrinter.h"
 #include "DirectX.h"
 #include "DirectXIRPasses/DXILDebugInfo.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Analysis/DXILResource.h"
 #include "llvm/IR/AssemblyAnnotationWriter.h"
@@ -262,17 +265,25 @@ static void prettyPrintResources(raw_ostream &OS, const DXILResourceMap &DRM,
 }
 
 namespace {
+class DXILModuleSlotTracker : public ModuleSlotTracker {
+public:
+  using ModuleSlotTracker::ModuleSlotTracker;
+  using ModuleSlotTracker::renumberMetadataForAssembly;
+};
+
 class DXILAssemblyAnnotationWriter : public llvm::AssemblyAnnotationWriter {
 private:
   ModuleSlotTracker &MST;
   AbstractSlotTrackerStorage &STS;
   const DXILDebugInfoMap &DI;
+  DenseSet<const MDNode *> &EmittedMDNodes;
 
 public:
   DXILAssemblyAnnotationWriter(ModuleSlotTracker &MST,
                                AbstractSlotTrackerStorage &STS,
-                               const DXILDebugInfoMap &DI)
-      : MST(MST), STS(STS), DI(DI) {}
+                               const DXILDebugInfoMap &DI,
+                               DenseSet<const MDNode *> &EmittedMDNodes)
+      : MST(MST), STS(STS), DI(DI), EmittedMDNodes(EmittedMDNodes) {}
 
   void emitInstructionAnnot(const Instruction *OrigI,
                             formatted_raw_ostream &os) override {
@@ -284,10 +295,11 @@ class DXILAssemblyAnnotationWriter : public llvm::AssemblyAnnotationWriter {
   }
 
   void emitMDNodeAnnot(const MDNode *N, formatted_raw_ostream &os) override {
+    EmittedMDNodes.insert(N);
+
     if (const Metadata *NewMD = DI.MDReplace.lookup(N)) {
       if (const auto *NewN = dyn_cast<MDNode>(NewMD))
-        if (STS.getMetadataSlot(NewN) == -1)
-          STS.createMetadataSlot(NewN);
+        STS.createMetadataSlot(NewN);
 
       os << "; DXIL: ";
       N->printAsOperand(os, MST);
@@ -299,8 +311,7 @@ class DXILAssemblyAnnotationWriter : public llvm::AssemblyAnnotationWriter {
 
     if (const Metadata *ExtraMD = DI.MDExtra.lookup(N)) {
       if (const auto *ExtraN = dyn_cast<MDNode>(ExtraMD))
-        if (STS.getMetadataSlot(ExtraN) == -1)
-          STS.createMetadataSlot(ExtraN);
+        STS.createMetadataSlot(ExtraN);
 
       os << "; DXIL: ";
       N->printAsOperand(os, MST);
@@ -313,36 +324,103 @@ class DXILAssemblyAnnotationWriter : public llvm::AssemblyAnnotationWriter {
 };
 } // namespace
 
+static SmallVector<const MDNode *>
+collectAdditionalMetadata(Module &M, const DXILDebugInfoMap &DI) {
+  // Annotation metadata follows module metadata in the order its keys print.
+  // Follow replacement graphs to preserve that order in canonical output.
+  M.renumberMetadataForAssembly();
+
+  ModuleSlotTracker MST(&M);
+  AbstractSlotTrackerStorage *STS = nullptr;
+  MST.setProcessHook(
+      [&](AbstractSlotTrackerStorage *STS_, const Module *) { STS = STS_; });
+  MDNode::get(M.getContext(), {})->print(llvm::nulls(), MST);
+  assert(STS && "Slot tracker storage should have been initialised");
+
+  DenseSet<const Metadata *> ReplacementMetadata;
+  for (auto [_, Replacement] : DI.MDReplace)
+    ReplacementMetadata.insert(Replacement);
+
+  SmallVector<std::pair<unsigned, const MDNode *>> OriginalNodes;
+  DenseSet<const MDNode *> Queued;
+  auto AddOriginal = [&](const Metadata *MD) {
+    const auto *N = dyn_cast<MDNode>(MD);
+    if (!N || ReplacementMetadata.contains(N) || !Queued.insert(N).second)
+      return;
+    OriginalNodes.emplace_back(STS->getMetadataSlot(N), N);
+  };
+  for (auto [Original, _] : DI.MDReplace)
+    AddOriginal(Original);
+  for (auto [Original, _] : DI.MDExtra)
+    AddOriginal(Original);
+  llvm::sort(OriginalNodes);
+
+  SmallVector<const MDNode *> Worklist;
+  for (auto [_, N] : OriginalNodes)
+    Worklist.push_back(N);
+
+  SmallVector<const MDNode *> AdditionalMetadata;
+  auto AddAdditional = [&](const Metadata *MD) {
+    const auto *Root = dyn_cast_or_null<MDNode>(MD);
+    if (!Root || Queued.contains(Root))
+      return;
+
+    AdditionalMetadata.push_back(Root);
+    SmallVector<const MDNode *> Nodes = {Root};
+    while (!Nodes.empty()) {
+      const MDNode *N = Nodes.pop_back_val();
+      if (!Queued.insert(N).second)
+        continue;
+      Worklist.push_back(N);
+      for (const MDOperand &Op : llvm::reverse(N->operands()))
+        if (const auto *OpNode = dyn_cast_or_null<MDNode>(Op.get()))
+          Nodes.push_back(OpNode);
+    }
+  };
+
+  for (size_t I = 0; I != Worklist.size(); ++I) {
+    const MDNode *N = Worklist[I];
+    if (const Metadata *Replacement = DI.MDReplace.lookup(N)) {
+      AddAdditional(Replacement);
+      continue;
+    }
+    AddAdditional(DI.MDExtra.lookup(N));
+  }
+  return AdditionalMetadata;
+}
+
 static void prettyPrint(raw_ostream &OS, Module &M, const DXILResourceMap &DRM,
                         DXILResourceTypeMap &DRTM, const DXILDebugInfoMap &DI) {
   formatted_raw_ostream FOS(OS);
 
   prettyPrintResources(FOS, DRM, DRTM);
 
-  ModuleSlotTracker MST(&M);
+  SmallVector<const MDNode *> AdditionalMetadata =
+      collectAdditionalMetadata(M, DI);
+  DXILModuleSlotTracker MST(&M);
+  MST.renumberMetadataForAssembly(AdditionalMetadata);
   AbstractSlotTrackerStorage *STS = nullptr;
-  unsigned NextMetadataSlot = 0;
   MST.setProcessHook(
-      [&](AbstractSlotTrackerStorage *STS_, const Module *, bool) {
-        STS = STS_;
-        NextMetadataSlot = STS->getNextMetadataSlot();
-      });
+      [&](AbstractSlotTrackerStorage *STS_, const Module *) { STS = STS_; });
   // Force initialisation. ModuleSlotTracker does not have a dedicated function
   // for this so trigger it through a dummy print.
   MDNode::get(M.getContext(), {})->print(llvm::nulls(), MST);
   assert(STS && "Slot tracker storage should have been initialised");
 
-  DXILAssemblyAnnotationWriter DAAW(MST, *STS, DI);
+  DenseSet<const MDNode *> EmittedMDNodes;
+  DXILAssemblyAnnotationWriter DAAW(MST, *STS, DI, EmittedMDNodes);
   M.print(FOS, &DAAW);
 
   ModuleSlotTracker::MachineMDNodeListType MDNodes;
-  MST.collectMDNodes(MDNodes, NextMetadataSlot, ~0u);
+  MST.collectMDNodes(MDNodes);
   std::sort(MDNodes.begin(), MDNodes.end(),
             [](const std::pair<unsigned, const MDNode *> &A,
                const std::pair<unsigned, const MDNode *> &B) {
               return A.first < B.first;
             });
   for (auto [_, MDNode] : MDNodes) {
+    if (EmittedMDNodes.contains(MDNode))
+      continue;
     DAAW.emitMDNodeAnnot(MDNode, FOS);
     MDNode->print(FOS, MST);
     FOS << "\n";
@@ -379,11 +457,11 @@ class DXILPrettyPrinterLegacy : public llvm::ModulePass {
 
 char DXILPrettyPrinterLegacy::ID = 0;
 INITIALIZE_PASS_BEGIN(DXILPrettyPrinterLegacy, "dxil-pretty-printer",
-                      "DXIL Pretty Printer", true, true)
+                      "DXIL Pretty Printer", true, false)
 INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass)
 INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass)
 INITIALIZE_PASS_END(DXILPrettyPrinterLegacy, "dxil-pretty-printer",
-                    "DXIL Pretty Printer", true, true)
+                    "DXIL Pretty Printer", true, false)
 
 bool DXILPrettyPrinterLegacy::runOnModule(Module &M) {
   const DXILResourceMap &DRM =
@@ -392,7 +470,7 @@ bool DXILPrettyPrinterLegacy::runOnModule(Module &M) {
       getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
   const DXILDebugInfoMap DI = DXILDebugInfoPass::run(M);
   prettyPrint(OS, M, DRM, DRTM, DI);
-  return DI.Modified;
+  return true;
 }
 
 ModulePass *llvm::createDXILPrettyPrinterLegacyPass(raw_ostream &OS) {
diff --git a/llvm/test/CodeGen/DirectX/DebugInfo/di-globalvariable.ll b/llvm/test/CodeGen/DirectX/DebugInfo/di-globalvariable.ll
index 978c6f6cfb221..fd23adbcd42b5 100644
--- a/llvm/test/CodeGen/DirectX/DebugInfo/di-globalvariable.ll
+++ b/llvm/test/CodeGen/DirectX/DebugInfo/di-globalvariable.ll
@@ -1,4 +1,5 @@
 ; RUN: llc %s -o - | FileCheck %s
+; RUN: llc %s -o - | FileCheck %s --check-prefix=NO-DUP
 
 target triple = "dxil-unknown-shadermodel6.3-library"
 
@@ -24,6 +25,12 @@ define void @foo() {
 ; CHECK-DAG: ![[FILE]] = !DIFile(filename: "cu.cpp", directory: "/tmp")
 ; CHECK-DAG: ![[TYPE]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
 
+; NO-DUP: ![[GVY:[0-9]+]] = !DIGlobalVariable(name: "y"
+; NO-DUP-NOT: ![[GVY]] =
+; NO-DUP: ![[GVX:[0-9]+]] = !DIGlobalVariable(name: "x"
+; NO-DUP-NOT: ![[GVX]] =
+; NO-DUP-NOT: ![[GVY]] =
+
 !llvm.dbg.cu = !{!4}
 !llvm.module.flags = !{!8, !9}
 
diff --git a/llvm/test/CodeGen/Hexagon/swp-no-alias.mir b/llvm/test/CodeGen/Hexagon/swp-no-alias.mir
index 38b7212702ff9..c37b9b32f8230 100644
--- a/llvm/test/CodeGen/Hexagon/swp-no-alias.mir
+++ b/llvm/test/CodeGen/Hexagon/swp-no-alias.mir
@@ -27,7 +27,7 @@
 # CHECK-DAG:      SU(4): Data Latency=0 Reg=%10
 # CHECK-DAG:      SU(2): Data Latency=0 Reg=%10
 # CHECK-DAG:      SU(7): Anti Latency=1
-# CHECK-NEXT: SU(2):   %12:hvxvr = V6_vL32b_ai %10:intregs, 0 :: (load (s1024) from %ir.iptr.09, !tbaa !4)
+# CHECK-NEXT: SU(2):   %12:hvxvr = V6_vL32b_ai %10:intregs, 0 :: (load (s1024) from %ir.iptr.09, !tbaa !10)
 # CHECK-NEXT:   # preds left
 # CHECK-NEXT:   # succs left
 # CHECK-NEXT:   # rdefs left
@@ -38,7 +38,7 @@
 # CHECK-NEXT:     SU(1): Data Latency=0 Reg=%10
 # CHECK-NEXT:   Successors:
 # CHECK-NEXT:     SU(3): Data Latency=0 Reg=%12
-# CHECK-NEXT: SU(3):   V6_vS32b_ai %8:intregs, 0, %12:hvxvr :: (store (s1024) into %ir.optr.010, !tbaa !4)
+# CHECK-NEXT: SU(3):   V6_vS32b_ai %8:intregs, 0, %12:hvxvr :: (store (s1024) into %ir.optr.010, !tbaa !10)
 # CHECK-NEXT:   # preds left
 # CHECK-NEXT:   # succs left
 # CHECK-NEXT:   # rdefs left
@@ -48,7 +48,7 @@
 # CHECK-NEXT:   Predecessors:
 # CHECK-DAG:      SU(2): Data Latency=0 Reg=%12
 # CHECK-DAG:      SU(0): Data Latency=0 Reg=%8
-# CHECK-NEXT: SU(4):   %13:hvxvr = V6_vL32b_ai %10:intregs, 128 :: (load (s1024) from %ir.cgep, !tbaa !4)
+# CHECK-NEXT: SU(4):   %13:hvxvr = V6_vL32b_ai %10:intregs, 128 :: (load (s1024) from %ir.cgep, !tbaa !10)
 # CHECK-NEXT:   # preds left
 # CHECK-NEXT:   # succs left
 # CHECK-NEXT:   # rdefs left
@@ -59,7 +59,7 @@
 # CHECK-NEXT:     SU(1): Data Latency=0 Reg=%10
 # CHECK-NEXT:   Successors:
 # CHECK-NEXT:     SU(5): Data Latency=0 Reg=%13
-# CHECK-NEXT: SU(5):   V6_vS32b_ai %8:intregs, 128, %13:hvxvr :: (store (s1024) into %ir.cgep3, !tbaa !4)
+# CHECK-NEXT: SU(5):   V6_vS32b_ai %8:intregs, 128, %13:hvxvr :: (store (s1024) into %ir.cgep3, !tbaa !10)
 
 
 
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/instr-mmra.mir b/llvm/test/CodeGen/MIR/AMDGPU/instr-mmra.mir
index 62593255ea4ab..7dce5c230df63 100644
--- a/llvm/test/CodeGen/MIR/AMDGPU/instr-mmra.mir
+++ b/llvm/test/CodeGen/MIR/AMDGPU/instr-mmra.mir
@@ -19,7 +19,7 @@ body:             |
     liveins: $vgpr0, $vgpr1
 
     ; CHECK-LABEL: name: test_mmra
-    ; CHECK: ATOMIC_FENCE 5, 2, mmra !0
+    ; CHECK: ATOMIC_FENCE 5, 2, mmra !{{[0-9]+}}
     ATOMIC_FENCE 5, 2, mmra !0
     S_ENDPGM 0
 ...
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/machine-metadata.mir b/llvm/test/CodeGen/MIR/AMDGPU/machine-metadata.mir
index 9570f8b98c468..45cf5a3fb7f7b 100644
--- a/llvm/test/CodeGen/MIR/AMDGPU/machine-metadata.mir
+++ b/llvm/test/CodeGen/MIR/AMDGPU/machine-metadata.mir
@@ -86,11 +86,11 @@ body:             |
     ; CHECK: [[REG_SEQUENCE:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY2]], %subreg.sub0, [[COPY1]], %subreg.sub1
     ; CHECK: [[REG_SEQUENCE1:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1
     ; CHECK: [[COPY5:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE1]]
-    ; CHECK: [[GLOBAL_LOAD_DWORDX4_:%[0-9]+]]:vreg_128 = GLOBAL_LOAD_DWORDX4 [[COPY5]], 16, 0, implicit $exec :: (load (s128) from %ir.p1, align 4, !alias.scope !5, !noalias !8, addrspace 1)
+    ; CHECK: [[GLOBAL_LOAD_DWORDX4_:%[0-9]+]]:vreg_128 = GLOBAL_LOAD_DWORDX4 [[COPY5]], 16, 0, implicit $exec :: (load (s128) from %ir.p1, align 4, !alias.scope ![[LOAD_SCOPE:[0-9]+]], !noalias ![[LOAD_NOALIAS:[0-9]+]], addrspace 1)
     ; CHECK: [[COPY6:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE1]]
-    ; CHECK: GLOBAL_STORE_DWORDX4 [[COPY6]], killed [[GLOBAL_LOAD_DWORDX4_]], 0, 0, implicit $exec :: (store (s128) into %ir.p0, align 4, !alias.scope !10, !noalias !11, addrspace 1)
+    ; CHECK: GLOBAL_STORE_DWORDX4 [[COPY6]], killed [[GLOBAL_LOAD_DWORDX4_]], 0, 0, implicit $exec :: (store (s128) into %ir.p0, align 4, !alias.scope ![[STORE_SCOPE:[0-9]+]], !noalias ![[STORE_NOALIAS:[0-9]+]], addrspace 1)
     ; CHECK: [[COPY7:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE]]
-    ; CHECK: [[GLOBAL_LOAD_DWORDX2_:%[0-9]+]]:vreg_64 = GLOBAL_LOAD_DWORDX2 killed [[COPY7]], 0, 0, implicit $exec :: (load (s64) from %ir.1, align 4, !alias.scope !3, !noalias !0, addrspace 1)
+    ; CHECK: [[GLOBAL_LOAD_DWORDX2_:%[0-9]+]]:vreg_64 = GLOBAL_LOAD_DWORDX2 killed [[COPY7]], 0, 0, implicit $exec :: (load (s64) from %ir.1, align 4, !alias.scope ![[IR_SCOPE:[0-9]+]], !noalias ![[IR_NOALIAS:[0-9]+]], addrspace 1)
     ; CHECK: [[COPY8:%[0-9]+]]:vgpr_32 = COPY [[GLOBAL_LOAD_DWORDX2_]].sub0
     ; CHECK: [[COPY9:%[0-9]+]]:vgpr_32 = COPY [[GLOBAL_LOAD_DWORDX2_]].sub1
     ; CHECK: [[V_ADD_U32_e64_:%[0-9]+]]:vgpr_32 = V_ADD_U32_e64 killed [[COPY8]], killed [[COPY9]], 0, implicit $exec
@@ -137,11 +137,11 @@ body:             |
     ; CHECK: [[REG_SEQUENCE:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY2]], %subreg.sub0, [[COPY1]], %subreg.sub1
     ; CHECK: [[REG_SEQUENCE1:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1
     ; CHECK: [[COPY5:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE1]]
-    ; CHECK: [[GLOBAL_LOAD_DWORDX4_:%[0-9]+]]:vreg_128 = GLOBAL_LOAD_DWORDX4 [[COPY5]], 16, 0, implicit $exec :: (load (s128) from %ir.p1, align 4, !alias.scope !5, !noalias !8, addrspace 1)
+    ; CHECK: [[GLOBAL_LOAD_DWORDX4_:%[0-9]+]]:vreg_128 = GLOBAL_LOAD_DWORDX4 [[COPY5]], 16, 0, implicit $exec :: (load (s128) from %ir.p1, align 4, !alias.scope ![[INLINE_LOAD_SCOPE:[0-9]+]], !noalias ![[INLINE_LOAD_NOALIAS:[0-9]+]], addrspace 1)
     ; CHECK: [[COPY6:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE1]]
-    ; CHECK: GLOBAL_STORE_DWORDX4 [[COPY6]], killed [[GLOBAL_LOAD_DWORDX4_]], 0, 0, implicit $exec :: (store (s128) into %ir.p0, align 4, !alias.scope !10, !noalias !11, addrspace 1)
+    ; CHECK: GLOBAL_STORE_DWORDX4 [[COPY6]], killed [[GLOBAL_LOAD_DWORDX4_]], 0, 0, implicit $exec :: (store (s128) into %ir.p0, align 4, !alias.scope ![[INLINE_STORE_SCOPE:[0-9]+]], !noalias ![[INLINE_STORE_NOALIAS:[0-9]+]], addrspace 1)
     ; CHECK: [[COPY7:%[0-9]+]]:vreg_64 = COPY [[REG_SEQUENCE]]
-    ; CHECK: [[GLOBAL_LOAD_DWORDX2_:%[0-9]+]]:vreg_64 = GLOBAL_LOAD_DWORDX2 killed [[COPY7]], 0, 0, implicit $exec :: (load (s64) from %ir.1, align 4, !alias.scope !3, !noalias !0, addrspace 1)
+    ; CHECK: [[GLOBAL_LOAD_DWORDX2_:%[0-9]+]]:vreg_64 = GLOBAL_LOAD_DWORDX2 killed [[COPY7]], 0, 0, implicit $exec :: (load (s64) from %ir.1, align 4, !alias.scope ![[IR_SCOPE]], !noalias ![[IR_NOALIAS]], addrspace 1)
     ; CHECK: [[COPY8:%[0-9]+]]:vgpr_32 = COPY [[GLOBAL_LOAD_DWORDX2_]].sub0
     ; CHECK: [[COPY9:%[0-9]+]]:vgpr_32 = COPY [[GLOBAL_LOAD_DWORDX2_]].sub1
     ; CHECK: [[V_ADD_U32_e64_:%[0-9]+]]:vgpr_32 = V_ADD_U32_e64 killed [[COPY8]], killed [[COPY9]], 0, implicit $exec
diff --git a/llvm/test/CodeGen/MIR/X86/instr-heap-alloc-operands.mir b/llvm/test/CodeGen/MIR/X86/instr-heap-alloc-operands.mir
index ca59e5fe7b8fd..724335cc371dc 100644
--- a/llvm/test/CodeGen/MIR/X86/instr-heap-alloc-operands.mir
+++ b/llvm/test/CodeGen/MIR/X86/instr-heap-alloc-operands.mir
@@ -34,7 +34,7 @@ body: |
     ADJCALLSTACKDOWN64 32, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
     $ecx = COPY %0
     CALL64pcrel32 @f, csr_win64, implicit $rsp, implicit $ssp, implicit $ecx, implicit-def $rsp, implicit-def $ssp, implicit-def dead $rax, heap-alloc-marker !2
-  ; CHECK: CALL64pcrel32 @f, {{.*}} heap-alloc-marker !2
+  ; CHECK: CALL64pcrel32 @f, {{.*}} heap-alloc-marker !{{[0-9]+}}
     ADJCALLSTACKUP64 32, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
     $eax = MOV32r0 implicit-def dead $eflags
     RET 0, killed $eax
diff --git a/llvm/test/CodeGen/MIR/X86/instr-pcsections.mir b/llvm/test/CodeGen/MIR/X86/instr-pcsections.mir
index 947d93ef35937..4a50838f45444 100644
--- a/llvm/test/CodeGen/MIR/X86/instr-pcsections.mir
+++ b/llvm/test/CodeGen/MIR/X86/instr-pcsections.mir
@@ -27,7 +27,7 @@ body:             |
     liveins: $rdi
 
     ; CHECK-LABEL: name: test
-    ; CHECK: MOV{{.*}} pcsections !0
+    ; CHECK: MOV{{.*}} pcsections !{{[0-9]+}}
     renamable $al = MOV8rm killed renamable $rdi, 1, $noreg, 0, $noreg, pcsections !0
     RET64 implicit killed $al
 
diff --git a/llvm/test/CodeGen/MIR/X86/instructions-debug-location.mir b/llvm/test/CodeGen/MIR/X86/instructions-debug-location.mir
index 11fed8ae64fd0..11b41182a36af 100644
--- a/llvm/test/CodeGen/MIR/X86/instructions-debug-location.mir
+++ b/llvm/test/CodeGen/MIR/X86/instructions-debug-location.mir
@@ -72,10 +72,10 @@ stack:
 body: |
   bb.0.entry:
     liveins: $edi
-    ; CHECK: DBG_VALUE $noreg, 0, !11, !DIExpression(), debug-location !12
-    ; CHECK: DBG_VALUE $noreg, 0, !11, !DIExpression(), debug-location !12
-    ; CHECK: $eax = COPY %0, debug-location !13
-    ; CHECK: RET64 $eax, debug-location !13
+    ; CHECK: DBG_VALUE $noreg, 0, ![[VAR:[0-9]+]], !DIExpression(), debug-location ![[VAR_LOC:[0-9]+]]
+    ; CHECK: DBG_VALUE $noreg, 0, ![[VAR]], !DIExpression(), debug-location ![[VAR_LOC]]
+    ; CHECK: $eax = COPY %0, debug-location ![[RET_LOC:[0-9]+]]
+    ; CHECK: RET64 $eax, debug-location ![[RET_LOC]]
     %0 = COPY $edi
     DBG_VALUE _, 0, !12, !DIExpression(), debug-location !13
     ; Test whether debug-use is still recognized for compatibility with old
@@ -99,9 +99,9 @@ body: |
     liveins: $edi
 
     %0 = COPY $edi
-  ; CHECK:      DBG_VALUE $noreg, i32 0, !11, !DIExpression()
-  ; CHECK-NEXT: DBG_VALUE $noreg, i64 -22, !11, !DIExpression()
-  ; CHECK-NEXT: DBG_VALUE $noreg, i128 123492148938512984928424384934328985928, !11, !DIExpression()
+  ; CHECK:      DBG_VALUE $noreg, i32 0, ![[VAR]], !DIExpression()
+  ; CHECK-NEXT: DBG_VALUE $noreg, i64 -22, ![[VAR]], !DIExpression()
+  ; CHECK-NEXT: DBG_VALUE $noreg, i128 123492148938512984928424384934328985928, ![[VAR]], !DIExpression()
     DBG_VALUE _, i32 0, !12, !DIExpression(), debug-location !13
     DBG_VALUE _, i64 -22, !12, !DIExpression(), debug-location !13
     DBG_VALUE _, i128 123492148938512984928424384934328985928, !12, !DIExpression(), debug-location !13
diff --git a/llvm/test/CodeGen/MIR/X86/machine-metadata.mir b/llvm/test/CodeGen/MIR/X86/machine-metadata.mir
index 47929752f1af8..cb782c88b40b4 100644
--- a/llvm/test/CodeGen/MIR/X86/machine-metadata.mir
+++ b/llvm/test/CodeGen/MIR/X86/machine-metadata.mir
@@ -76,12 +76,12 @@ body:             |
     ; CHECK-LABEL: name: test_memcpy
     ; CHECK: [[COPY:%[0-9]+]]:gr64 = COPY $rsi
     ; CHECK: [[COPY1:%[0-9]+]]:gr64 = COPY $rdi
-    ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 16, $noreg :: (load (s64) from %ir.p1, align 4, !alias.scope !5, !noalias !8)
-    ; CHECK: [[MOV64rm1:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 24, $noreg :: (load (s64) from %ir.p1 + 8, align 4, !alias.scope !5, !noalias !8)
-    ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 8, $noreg, killed [[MOV64rm1]] :: (store (s64) into %ir.p0 + 8, align 4, !alias.scope !10, !noalias !11)
-    ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 0, $noreg, killed [[MOV64rm]] :: (store (s64) into %ir.p0, align 4, !alias.scope !10, !noalias !11)
-    ; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm [[COPY]], 1, $noreg, 0, $noreg :: (load (s32) from %ir.q, !alias.scope !3, !noalias !0)
-    ; CHECK: [[ADD32rm:%[0-9]+]]:gr32 = ADD32rm [[MOV32rm]], [[COPY]], 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load (s32) from %ir.q1, !alias.scope !3, !noalias !0)
+    ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 16, $noreg :: (load (s64) from %ir.p1, align 4, !alias.scope ![[MEMCPY_LOAD_SCOPE:[0-9]+]], !noalias ![[MEMCPY_LOAD_NOALIAS:[0-9]+]])
+    ; CHECK: [[MOV64rm1:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 24, $noreg :: (load (s64) from %ir.p1 + 8, align 4, !alias.scope ![[MEMCPY_LOAD_SCOPE]], !noalias ![[MEMCPY_LOAD_NOALIAS]])
+    ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 8, $noreg, killed [[MOV64rm1]] :: (store (s64) into %ir.p0 + 8, align 4, !alias.scope ![[MEMCPY_STORE_SCOPE:[0-9]+]], !noalias ![[MEMCPY_STORE_NOALIAS:[0-9]+]])
+    ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 0, $noreg, killed [[MOV64rm]] :: (store (s64) into %ir.p0, align 4, !alias.scope ![[MEMCPY_STORE_SCOPE]], !noalias ![[MEMCPY_STORE_NOALIAS]])
+    ; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm [[COPY]], 1, $noreg, 0, $noreg :: (load (s32) from %ir.q, !alias.scope ![[IR_SCOPE:[0-9]+]], !noalias ![[IR_NOALIAS:[0-9]+]])
+    ; CHECK: [[ADD32rm:%[0-9]+]]:gr32 = ADD32rm [[MOV32rm]], [[COPY]], 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load (s32) from %ir.q1, !alias.scope ![[IR_SCOPE]], !noalias ![[IR_NOALIAS]])
     ; CHECK: $eax = COPY [[ADD32rm]]
     ; CHECK: RET 0, $eax
     %1:gr64 = COPY $rsi
@@ -113,12 +113,12 @@ body:             |
     ; CHECK-LABEL: name: test_memcpy_inline
     ; CHECK: [[COPY:%[0-9]+]]:gr64 = COPY $rsi
     ; CHECK: [[COPY1:%[0-9]+]]:gr64 = COPY $rdi
-    ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 16, $noreg :: (load (s64) from %ir.p1, align 4, !alias.scope !5, !noalias !8)
-    ; CHECK: [[MOV64rm1:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 24, $noreg :: (load (s64) from %ir.p1 + 8, align 4, !alias.scope !5, !noalias !8)
-    ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 8, $noreg, killed [[MOV64rm1]] :: (store (s64) into %ir.p0 + 8, align 4, !alias.scope !10, !noalias !11)
-    ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 0, $noreg, killed [[MOV64rm]] :: (store (s64) into %ir.p0, align 4, !alias.scope !10, !noalias !11)
-    ; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm [[COPY]], 1, $noreg, 0, $noreg :: (load (s32) from %ir.q, !alias.scope !3, !noalias !0)
-    ; CHECK: [[ADD32rm:%[0-9]+]]:gr32 = ADD32rm [[MOV32rm]], [[COPY]], 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load (s32) from %ir.q1, !alias.scope !3, !noalias !0)
+    ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 16, $noreg :: (load (s64) from %ir.p1, align 4, !alias.scope ![[INLINE_LOAD_SCOPE:[0-9]+]], !noalias ![[INLINE_LOAD_NOALIAS:[0-9]+]])
+    ; CHECK: [[MOV64rm1:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 24, $noreg :: (load (s64) from %ir.p1 + 8, align 4, !alias.scope ![[INLINE_LOAD_SCOPE]], !noalias ![[INLINE_LOAD_NOALIAS]])
+    ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 8, $noreg, killed [[MOV64rm1]] :: (store (s64) into %ir.p0 + 8, align 4, !alias.scope ![[INLINE_STORE_SCOPE:[0-9]+]], !noalias ![[INLINE_STORE_NOALIAS:[0-9]+]])
+    ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 0, $noreg, killed [[MOV64rm]] :: (store (s64) into %ir.p0, align 4, !alias.scope ![[INLINE_STORE_SCOPE]], !noalias ![[INLINE_STORE_NOALIAS]])
+    ; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm [[COPY]], 1, $noreg, 0, $noreg :: (load (s32) from %ir.q, !alias.scope ![[IR_SCOPE]], !noalias ![[IR_NOALIAS]])
+    ; CHECK: [[ADD32rm:%[0-9]+]]:gr32 = ADD32rm [[MOV32rm]], [[COPY]], 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load (s32) from %ir.q1, !alias.scope ![[IR_SCOPE]], !noalias ![[IR_NOALIAS]])
     ; CHECK: $eax = COPY [[ADD32rm]]
     ; CHECK: RET 0, $eax
     %1:gr64 = COPY $rsi
@@ -150,12 +150,12 @@ body:             |
     ; CHECK-LABEL: name: test_mempcpy
     ; CHECK: [[COPY:%[0-9]+]]:gr64 = COPY $rsi
     ; CHECK: [[COPY1:%[0-9]+]]:gr64 = COPY $rdi
-    ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 16, $noreg :: (load (s64) from %ir.p1, align 1, !alias.scope !5, !noalias !8)
-    ; CHECK: [[MOV64rm1:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 24, $noreg :: (load (s64) from %ir.p1 + 8, align 1, !alias.scope !5, !noalias !8)
-    ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 8, $noreg, killed [[MOV64rm1]] :: (store (s64) into %ir.p0 + 8, align 1, !alias.scope !10, !noalias !11)
-    ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 0, $noreg, killed [[MOV64rm]] :: (store (s64) into %ir.p0, align 1, !alias.scope !10, !noalias !11)
-    ; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm [[COPY]], 1, $noreg, 0, $noreg :: (load (s32) from %ir.q, !alias.scope !3, !noalias !0)
-    ; CHECK: [[ADD32rm:%[0-9]+]]:gr32 = ADD32rm [[MOV32rm]], [[COPY]], 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load (s32) from %ir.q1, !alias.scope !3, !noalias !0)
+    ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 16, $noreg :: (load (s64) from %ir.p1, align 1, !alias.scope ![[MEMPCPY_LOAD_SCOPE:[0-9]+]], !noalias ![[MEMPCPY_LOAD_NOALIAS:[0-9]+]])
+    ; CHECK: [[MOV64rm1:%[0-9]+]]:gr64 = MOV64rm [[COPY1]], 1, $noreg, 24, $noreg :: (load (s64) from %ir.p1 + 8, align 1, !alias.scope ![[MEMPCPY_LOAD_SCOPE]], !noalias ![[MEMPCPY_LOAD_NOALIAS]])
+    ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 8, $noreg, killed [[MOV64rm1]] :: (store (s64) into %ir.p0 + 8, align 1, !alias.scope ![[MEMPCPY_STORE_SCOPE:[0-9]+]], !noalias ![[MEMPCPY_STORE_NOALIAS:[0-9]+]])
+    ; CHECK: MOV64mr [[COPY1]], 1, $noreg, 0, $noreg, killed [[MOV64rm]] :: (store (s64) into %ir.p0, align 1, !alias.scope ![[MEMPCPY_STORE_SCOPE]], !noalias ![[MEMPCPY_STORE_NOALIAS]])
+    ; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm [[COPY]], 1, $noreg, 0, $noreg :: (load (s32) from %ir.q, !alias.scope ![[IR_SCOPE]], !noalias ![[IR_NOALIAS]])
+    ; CHECK: [[ADD32rm:%[0-9]+]]:gr32 = ADD32rm [[MOV32rm]], [[COPY]], 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load (s32) from %ir.q1, !alias.scope ![[IR_SCOPE]], !noalias ![[IR_NOALIAS]])
     ; CHECK: $eax = COPY [[ADD32rm]]
     ; CHECK: RET 0, $eax
     %1:gr64 = COPY $rsi
diff --git a/llvm/test/CodeGen/MIR/X86/mem-cache-hint.mir b/llvm/test/CodeGen/MIR/X86/mem-cache-hint.mir
index 196307e14ef1d..f59023de10e77 100644
--- a/llvm/test/CodeGen/MIR/X86/mem-cache-hint.mir
+++ b/llvm/test/CodeGen/MIR/X86/mem-cache-hint.mir
@@ -28,9 +28,9 @@ body: |
     ; CHECK: liveins: $rdi, $esi
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: [[COPY:%[0-9]+]]:gr64 = COPY $rdi
-    ; CHECK-NEXT: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm [[COPY]], 1, $noreg, 0, $noreg :: (load (s32) from %ir.p, !mem.cache_hint !0)
+    ; CHECK-NEXT: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm [[COPY]], 1, $noreg, 0, $noreg :: (load (s32) from %ir.p, !mem.cache_hint !{{[0-9]+}})
     ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr32 = COPY $esi
-    ; CHECK-NEXT: MOV32mr [[COPY]], 1, $noreg, 0, $noreg, [[COPY1]] :: (store (s32) into %ir.p, !mem.cache_hint !2)
+    ; CHECK-NEXT: MOV32mr [[COPY]], 1, $noreg, 0, $noreg, [[COPY1]] :: (store (s32) into %ir.p, !mem.cache_hint !{{[0-9]+}})
     ; CHECK-NEXT: $eax = COPY [[MOV32rm]]
     ; CHECK-NEXT: RET 0, $eax
     %0:gr64 = COPY $rdi
diff --git a/llvm/test/CodeGen/MIR/X86/memory-operands.mir b/llvm/test/CodeGen/MIR/X86/memory-operands.mir
index 60a5a4b192aed..b738dd9b12b51 100644
--- a/llvm/test/CodeGen/MIR/X86/memory-operands.mir
+++ b/llvm/test/CodeGen/MIR/X86/memory-operands.mir
@@ -459,8 +459,8 @@ body: |
   bb.0.entry:
     $rax = MOV64rm $rip, 1, _, @a, _ :: (load (s64) from got)
   ; CHECK-LABEL: name: tbaa_metadata
-  ; CHECK:      $eax = MOV32rm killed $rax, 1, $noreg, 0, $noreg, implicit-def $rax :: (load (s32) from @a, !tbaa !2)
-  ; CHECK-NEXT: $eax = MOV32rm killed $rax, 1, $noreg, 0, $noreg :: (load (s32) from %ir.1, !tbaa !6)
+  ; CHECK:      $eax = MOV32rm killed $rax, 1, $noreg, 0, $noreg, implicit-def $rax :: (load (s32) from @a, !tbaa !{{[0-9]+}})
+  ; CHECK-NEXT: $eax = MOV32rm killed $rax, 1, $noreg, 0, $noreg :: (load (s32) from %ir.1, !tbaa !{{[0-9]+}})
     $eax = MOV32rm killed $rax, 1, _, 0, _, implicit-def $rax :: (load (s32) from @a, !tbaa !2)
     $eax = MOV32rm killed $rax, 1, _, 0, _ :: (load (s32) from %ir.1, !tbaa !6)
     RET64 $eax
@@ -475,9 +475,9 @@ body: |
   bb.0.entry:
     liveins: $rdi, $rsi
   ; CHECK-LABEL: name: aa_scope
-  ; CHECK: $xmm0 = MOVSSrm_alt $rsi, 1, $noreg, 0, $noreg :: (load (s32) from %ir.c, !alias.scope !9)
+  ; CHECK: $xmm0 = MOVSSrm_alt $rsi, 1, $noreg, 0, $noreg :: (load (s32) from %ir.c, !alias.scope ![[AA_SCOPE:[0-9]+]])
     $xmm0 = MOVSSrm_alt $rsi, 1, _, 0, _ :: (load (s32) from %ir.c, !alias.scope !9)
-  ; CHECK-NEXT: MOVSSmr $rdi, 1, $noreg, 20, $noreg, killed $xmm0 :: (store (s32) into %ir.arrayidx.i, !noalias !9)
+  ; CHECK-NEXT: MOVSSmr $rdi, 1, $noreg, 20, $noreg, killed $xmm0 :: (store (s32) into %ir.arrayidx.i, !noalias ![[AA_SCOPE]])
     MOVSSmr $rdi, 1, _, 20, _, killed $xmm0 :: (store (s32) into %ir.arrayidx.i, !noalias !9)
     $xmm0 = MOVSSrm_alt killed $rsi, 1, _, 0, _ :: (load (s32) from %ir.c)
     MOVSSmr killed $rdi, 1, _, 28, _, killed $xmm0 :: (store (s32) into %ir.arrayidx)
@@ -492,7 +492,7 @@ body: |
   bb.0.entry:
     liveins: $rdi
   ; CHECK-LABEL: name: range_metadata
-  ; CHECK: $al = MOV8rm killed $rdi, 1, $noreg, 0, $noreg :: (load (s8) from %ir.x, !range !11, !mem.cache_hint !12)
+  ; CHECK: $al = MOV8rm killed $rdi, 1, $noreg, 0, $noreg :: (load (s8) from %ir.x, !range !{{[0-9]+}}, !mem.cache_hint !{{[0-9]+}})
     $al = MOV8rm killed $rdi, 1, _, 0, _ :: (load (s8) from %ir.x, !range !11, !mem.cache_hint !12)
     RET64 $al
 ...
diff --git a/llvm/test/CodeGen/MIR/X86/metadata-operands.mir b/llvm/test/CodeGen/MIR/X86/metadata-operands.mir
index c80af7dd6501c..063b04e828b24 100644
--- a/llvm/test/CodeGen/MIR/X86/metadata-operands.mir
+++ b/llvm/test/CodeGen/MIR/X86/metadata-operands.mir
@@ -51,7 +51,7 @@ body: |
   bb.0.entry:
     liveins: $edi
     ; CHECK:      %0:gr32 = COPY $edi
-    ; CHECK-NEXT: DBG_VALUE $noreg, 0, !11, !DIExpression()
+    ; CHECK-NEXT: DBG_VALUE $noreg, 0, !{{[0-9]+}}, !DIExpression()
     %0 = COPY $edi
     DBG_VALUE _, 0, !12, !DIExpression(), debug-location !13
     MOV32mr %stack.0.x.addr, 1, _, 0, _, %0
diff --git a/llvm/test/CodeGen/MIR/X86/pr38773.mir b/llvm/test/CodeGen/MIR/X86/pr38773.mir
index 1d4be4b23f400..32b175775f63a 100644
--- a/llvm/test/CodeGen/MIR/X86/pr38773.mir
+++ b/llvm/test/CodeGen/MIR/X86/pr38773.mir
@@ -97,14 +97,14 @@ body:             |
     IDIV32r killed renamable $ecx, implicit-def $eax, implicit-def dead $edx, implicit-def dead $eflags, implicit $eax, implicit killed $edx
     renamable $ecx = COPY $eax
     ; CHECK:        IDIV32r killed renamable $ecx
-    ; CHECK-NEXT:   DBG_VALUE $eax, $noreg, !12, !DIExpression(), debug-location !13
+    ; CHECK-NEXT:   DBG_VALUE $eax, $noreg, ![[VAR:[0-9]+]], !DIExpression(), debug-location ![[LOC:[0-9]+]]
     DBG_VALUE $ecx, $noreg, !12, !DIExpression(), debug-location !13
     ; The following mov and DBG_VALUE have been inserted after the PR was
     ; resolved to check that MCP will update debug users that are not
     ; immediately after the dead copy.
     ; CHECK-NEXT:   $edx = MOV32r0
     $edx = MOV32r0 implicit-def dead $eflags
-    ; CHECK-NEXT:   DBG_VALUE $eax, $noreg, !12, !DIExpression(), debug-location !13
+    ; CHECK-NEXT:   DBG_VALUE $eax, $noreg, ![[VAR]], !DIExpression(), debug-location ![[LOC]]
     DBG_VALUE $ecx, $noreg, !12, !DIExpression(), debug-location !13
     $eax = COPY killed renamable $ecx
     RET 0, $eax
diff --git a/llvm/test/CodeGen/MIR/X86/stack-object-debug-info.mir b/llvm/test/CodeGen/MIR/X86/stack-object-debug-info.mir
index 416f8cfbaed0a..c34622fe8512a 100644
--- a/llvm/test/CodeGen/MIR/X86/stack-object-debug-info.mir
+++ b/llvm/test/CodeGen/MIR/X86/stack-object-debug-info.mir
@@ -54,8 +54,8 @@ frameInfo:
 # CHECK: stack:
 # CHECK:  - { id: 0, name: y.i, type: default, offset: 0, size: 256, alignment: 16,
 # CHECK-NEXT: callee-saved-register: '', callee-saved-restored: true,
-# CHECK-NEXT: debug-info-variable: '!4', debug-info-expression: '!DIExpression()',
-# CHECK-NEXT: debug-info-location: '!12' }
+# CHECK-NEXT: debug-info-variable: '!{{[0-9]+}}', debug-info-expression: '!DIExpression()',
+# CHECK-NEXT: debug-info-location: '!{{[0-9]+}}' }
 stack:
   - { id: 0, name: y.i, offset: 0, size: 256, alignment: 16,
       debug-info-variable: '!4', debug-info-expression: '!DIExpression()',
diff --git a/llvm/test/DebugInfo/MIR/AArch64/no-dbg-value-after-terminator.mir b/llvm/test/DebugInfo/MIR/AArch64/no-dbg-value-after-terminator.mir
index 34c099f27becb..586e5abc16e8b 100644
--- a/llvm/test/DebugInfo/MIR/AArch64/no-dbg-value-after-terminator.mir
+++ b/llvm/test/DebugInfo/MIR/AArch64/no-dbg-value-after-terminator.mir
@@ -5,7 +5,7 @@
 # CHECK-NEXT: - function:    f1
 # CHECK-NEXT: - basic block: %bb.0
 # CHECK-NEXT: - instruction: DBG_VALUE $noreg, $noreg, !"1", !DIExpression(DW_OP_LLVM_entry_value, 1)
-# CHECK-NEXT: First terminator was:   RET undef $lr, debug-location !12; /tmp/foo.ll:2:1
+# CHECK-NEXT: First terminator was:   RET undef $lr, debug-location !26; /tmp/foo.ll:2:1
 
 --- |
   target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
diff --git a/llvm/test/Other/legacy-callgraph-scc-pass-printer.ll b/llvm/test/Other/legacy-callgraph-scc-pass-printer.ll
index fda04f6740575..341584508ea79 100644
--- a/llvm/test/Other/legacy-callgraph-scc-pass-printer.ll
+++ b/llvm/test/Other/legacy-callgraph-scc-pass-printer.ll
@@ -1,11 +1,22 @@
 ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -enable-ipra \
 ; RUN:     -print-after=DummyCGSCCPass -o - %s 2>&1 | FileCheck %s
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu -enable-ipra \
+; RUN:     -print-after=DummyCGSCCPass -print-module-scope -o - %s 2>&1 \
+; RUN:     | FileCheck %s --check-prefix=PERSISTENT
 ; REQUIRES: x86-registered-target
 
 ; The legacy CallGraphSCCPass printer should emit the banner as its own line.
 ; CHECK-LABEL: *** IR Dump After DummyCGSCCPass (DummyCGSCCPass) ***
 ; CHECK-NEXT: define void @bar() {
 
+; PERSISTENT-LABEL: *** IR Dump After DummyCGSCCPass (DummyCGSCCPass) ***
+; PERSISTENT: define void @bar() {
+; PERSISTENT: ret void, !annotation ![[USED:[0-9]+]]
+; PERSISTENT: ![[USED]] = !{!"used"}
+
 define void @bar() {
-  ret void
+  ret void, !annotation !1
 }
+
+!0 = !{!"unused"}
+!1 = !{!"used"}
diff --git a/llvm/test/Other/print-changed-persistent-metadata-ids.ll b/llvm/test/Other/print-changed-persistent-metadata-ids.ll
new file mode 100644
index 0000000000000..01cb0eb3fb548
--- /dev/null
+++ b/llvm/test/Other/print-changed-persistent-metadata-ids.ll
@@ -0,0 +1,77 @@
+; RUN: opt -passes=instsimplify -filter-print-funcs=second \
+; RUN:   -print-changed=quiet -disable-output < %s 2>&1 | FileCheck %s --check-prefix=CHANGED
+; RUN: opt -passes=instsimplify -filter-print-funcs=second \
+; RUN:   -print-before=instsimplify -print-after=instsimplify \
+; RUN:   -disable-output < %s 2>&1 | FileCheck %s --check-prefix=STABLE
+; RUN: opt -passes='function(instsimplify),globaldce' -filter-print-funcs=second \
+; RUN:   -print-changed=quiet -print-module-scope -disable-output < %s 2>&1 \
+; RUN:   | FileCheck %s --check-prefix=CROSS-KIND
+; RUN: opt -passes='function(instsimplify),print' -disable-output < %s 2> %t
+; RUN: FileCheck %s --check-prefix=SPARSE < %t
+; RUN: opt -disable-output < %t
+; RUN: opt -S -passes='function(instsimplify)' < %s \
+; RUN:   | FileCheck %s --check-prefix=COMPACT
+
+declare i32 @opaque(i32)
+
+ at dead = internal global i32 0
+
+define i32 @first(i32 %arg) #0 {
+  %keep = call i32 @opaque(i32 %arg)
+  ret i32 %keep
+}
+
+define i32 @second(i32 %arg) #1 {
+  %constant = add i32 2, 3, !annotation !0
+  %keep = call i32 @opaque(i32 %arg), !annotation !1, !other !3
+  %result = add i32 %keep, %constant
+  ret i32 %result
+}
+
+!0 = !{!"removed metadata"}
+!1 = !{!2}
+!2 = !{!"second metadata"}
+!3 = !{!"other metadata"}
+
+attributes #0 = { nounwind }
+attributes #1 = { noinline }
+
+; CHANGED: *** IR Dump After InstSimplifyPass on second ***
+; CHANGED: define i32 @second(i32 %arg) #1 {
+; CHANGED: %keep = call i32 @opaque(i32 %arg)
+; CHANGED-SAME: !annotation ![[ANNOTATION:[0-9]+]], !other ![[OTHER:[0-9]+]]
+
+; STABLE: *** IR Dump Before InstSimplifyPass on second ***
+; STABLE: %constant = add i32 2, 3, !annotation !{{[0-9]+}}
+; STABLE: %keep = call i32 @opaque(i32 %arg)
+; STABLE-SAME: !annotation ![[STABLE_ANNOTATION:[0-9]+]], !other ![[STABLE_OTHER:[0-9]+]]
+; STABLE: *** IR Dump After InstSimplifyPass on second ***
+; STABLE-NOT: %constant
+; STABLE: %keep = call i32 @opaque(i32 %arg)
+; STABLE-SAME: !annotation ![[STABLE_ANNOTATION]], !other ![[STABLE_OTHER]]
+
+; CROSS-KIND: *** IR Dump After InstSimplifyPass on second ***
+; CROSS-KIND: @dead = internal global i32 0
+; CROSS-KIND: define i32 @second(i32 %arg) #1 {
+; CROSS-KIND: %keep = call i32 @opaque(i32 %arg)
+; CROSS-KIND-SAME: !annotation ![[CROSS_ANNOTATION:[0-9]+]], !other ![[CROSS_OTHER:[0-9]+]]
+; CROSS-KIND: *** IR Dump After GlobalDCEPass on [module] ***
+; CROSS-KIND-NOT: @dead
+; CROSS-KIND: define i32 @second(i32 %arg) #1 {
+; CROSS-KIND: %keep = call i32 @opaque(i32 %arg)
+; CROSS-KIND-SAME: !annotation ![[CROSS_ANNOTATION]], !other ![[CROSS_OTHER]]
+
+; SPARSE: define i32 @second(i32 %arg) #1 {
+; SPARSE: %keep = call i32 @opaque(i32 %arg)
+; SPARSE-SAME: !annotation ![[SPARSE_ANNOTATION:[1-9][0-9]*]], !other ![[SPARSE_OTHER:[0-9]+]]
+; SPARSE-NOT: !0 =
+; SPARSE: ![[SPARSE_ANNOTATION]] = !{![[SPARSE_NESTED:[0-9]+]]}
+; SPARSE-DAG: ![[SPARSE_NESTED]] = !{!"second metadata"}
+; SPARSE-DAG: ![[SPARSE_OTHER]] = !{!"other metadata"}
+
+; COMPACT: define i32 @second(i32 %arg) #1 {
+; COMPACT: %keep = call i32 @opaque(i32 %arg)
+; COMPACT-SAME: !annotation !0, !other !2
+; COMPACT: !0 = !{!1}
+; COMPACT: !1 = !{!"second metadata"}
+; COMPACT: !2 = !{!"other metadata"}
diff --git a/llvm/test/Other/print-persistent-metadata-ids.ll b/llvm/test/Other/print-persistent-metadata-ids.ll
new file mode 100644
index 0000000000000..79ae153353d02
--- /dev/null
+++ b/llvm/test/Other/print-persistent-metadata-ids.ll
@@ -0,0 +1,94 @@
+; RUN: opt -S -passes=no-op-module < %s | FileCheck %s --check-prefix=COMPACT
+; RUN: opt -disable-output -passes=print < %s 2>&1 | FileCheck %s --check-prefix=PERSISTENT-MODULE
+; RUN: opt -disable-output -passes=print < %s 2> %t
+; RUN: opt -disable-output < %t
+; RUN: opt -disable-output -passes='function(print)' -filter-print-funcs=second \
+; RUN:   < %s 2>&1 | FileCheck %s --check-prefix=PERSISTENT-FUNCTION
+; RUN: opt -disable-output -passes='function(no-op-function)' \
+; RUN:   -print-before=no-op-function -filter-print-funcs=second \
+; RUN:   < %s 2>&1 | FileCheck %s --check-prefix=PERSISTENT-FUNCTION
+; RUN: opt -disable-output -passes='function(no-op-function)' -print-after-all \
+; RUN:   -filter-print-funcs=second < %s 2>&1 | FileCheck %s --check-prefix=PERSISTENT-FUNCTION
+; RUN: opt -disable-output -passes=no-op-module -print-before=no-op-module \
+; RUN:   -filter-print-funcs=first,second < %s 2>&1 | FileCheck %s --check-prefix=PERSISTENT-MULTI
+; RUN: opt -disable-output -passes='loop(no-op-loop)' -print-before=no-op-loop \
+; RUN:   -filter-print-funcs=loop < %s 2>&1 | FileCheck %s --check-prefix=PERSISTENT-LOOP
+; RUN: opt -disable-output -passes='print,function(print)' < %s 2>&1 | FileCheck %s --check-prefix=SAME-ID
+$group = comdat any
+
+ at named = global ptr @0, comdat($group), !annotation !5
+ at 0 = global i32 0
+ at 1 = global i32 1
+
+declare void @callee(ptr)
+
+define void @first() #0 {
+  call void @callee(ptr @0) #1
+  call void @callee(ptr @1) #1
+  ret void, !annotation !1
+}
+
+define void @second() {
+  call void @callee(ptr @1) #1, !annotation !3
+  ret void, !annotation !3
+}
+
+define void @loop() {
+entry:
+  call void @callee(ptr @0) #1
+  call void @callee(ptr @1) #1
+  br label %loop
+
+loop:
+  call void @callee(ptr @1) #1
+  br i1 false, label %loop, label %exit
+
+exit:
+  ret void
+}
+
+attributes #0 = { noinline }
+attributes #1 = { nounwind }
+
+!named = !{!0}
+!0 = !{!"named metadata"}
+!1 = !{!2}
+!2 = !{!"first metadata"}
+!3 = !{!4}
+!4 = !{!"second metadata"}
+!5 = !{!6}
+!6 = !{!"global metadata"}
+
+; COMPACT: @named = global ptr @0, comdat($group), !annotation !0
+; COMPACT: ret void, !annotation !3
+; COMPACT: call void @callee(ptr @1) #1, !annotation !5
+; COMPACT: ret void, !annotation !5
+; COMPACT: !named = !{!2}
+
+; PERSISTENT-MODULE: @named = global ptr @0, comdat($group), !annotation ![[GLOBAL:[0-9]+]]
+; PERSISTENT-MODULE: ret void, !annotation ![[FIRST:[0-9]+]]
+; PERSISTENT-MODULE: call void @callee(ptr @1) #1, !annotation ![[SECOND:[0-9]+]]
+; PERSISTENT-MODULE: ret void, !annotation ![[SECOND]]
+; PERSISTENT-MODULE: !named = !{![[NAMED:[0-9]+]]}
+
+; PERSISTENT-FUNCTION: define void @second() {
+; PERSISTENT-FUNCTION: call void @callee(ptr @1) #1, !annotation ![[SECOND:[0-9]+]]
+; PERSISTENT-FUNCTION: ret void, !annotation ![[SECOND]]
+
+; PERSISTENT-MULTI: define void @first() #0 {
+; PERSISTENT-MULTI: call void @callee(ptr @0) #1
+; PERSISTENT-MULTI: call void @callee(ptr @1) #1
+; PERSISTENT-MULTI: define void @second() {
+; PERSISTENT-MULTI: call void @callee(ptr @1) #1
+
+; PERSISTENT-LOOP: ; Preheader:
+; PERSISTENT-LOOP: call void @callee(ptr @0) #1
+; PERSISTENT-LOOP: call void @callee(ptr @1) #1
+; PERSISTENT-LOOP: ; Loop:
+; PERSISTENT-LOOP: call void @callee(ptr @1) #1
+
+; SAME-ID: define void @second() {
+; SAME-ID: call void @callee(ptr @1) #1, !annotation ![[SAME_SECOND:[0-9]+]]
+; SAME-ID: ![[SAME_SECOND]] = !{!{{[0-9]+}}}
+; SAME-ID: define void @second() {
+; SAME-ID: call void @callee(ptr @1) #1, !annotation ![[SAME_SECOND]]
diff --git a/llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/Inputs/loop-distribute.ll.expected b/llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/Inputs/loop-distribute.ll.expected
index b2cd7cc79a70c..e3e62c44f6ce4 100644
--- a/llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/Inputs/loop-distribute.ll.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_analyze_test_checks/Inputs/loop-distribute.ll.expected
@@ -72,12 +72,12 @@ define void @ldist(i1 %cond, ptr %A, ptr %B, ptr %C) {
 ; CHECK-NEXT:  LDist: Partition 0:
 ; CHECK-NEXT:  for.body.ldist1: ; preds = %if.end.ldist1, %for.body.ph.ldist1
 ; CHECK-NEXT:    %iv.ldist1 = phi i16 [ 0, %for.body.ph.ldist1 ], [ %iv.next.ldist1, %if.end.ldist1 ]
-; CHECK-NEXT:    %lv.ldist1 = load i16, ptr %A, align 1, !alias.scope !2, !noalias !5
-; CHECK-NEXT:    store i16 %lv.ldist1, ptr %A, align 1, !alias.scope !2, !noalias !5
+; CHECK-NEXT:    %lv.ldist1 = load i16, ptr %A, align 1, !alias.scope !5, !noalias !4
+; CHECK-NEXT:    store i16 %lv.ldist1, ptr %A, align 1, !alias.scope !5, !noalias !4
 ; CHECK-NEXT:    br i1 %cond, label %if.then.ldist1, label %if.end.ldist1
 ; CHECK-EMPTY:
 ; CHECK-NEXT:  if.then.ldist1: ; preds = %for.body.ldist1
-; CHECK-NEXT:    %lv2.ldist1 = load i16, ptr %A, align 1, !alias.scope !2, !noalias !5
+; CHECK-NEXT:    %lv2.ldist1 = load i16, ptr %A, align 1, !alias.scope !5, !noalias !4
 ; CHECK-NEXT:    br label %if.end.ldist1
 ; CHECK-EMPTY:
 ; CHECK-NEXT:  if.end.ldist1: ; preds = %if.then.ldist1, %for.body.ldist1
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/IR/01-ir-print-basic-details.test b/llvm/test/tools/llvm-debuginfo-analyzer/IR/01-ir-print-basic-details.test
index 51a807942c48e..b11128d164ea7 100644
--- a/llvm/test/tools/llvm-debuginfo-analyzer/IR/01-ir-print-basic-details.test
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/IR/01-ir-print-basic-details.test
@@ -40,11 +40,11 @@
 ; ONE-NEXT: [003]                 {Block}
 ; ONE-NEXT: [004]     5             {Variable} 'CONSTANT' -> 'const INTEGER'
 ; ONE-NEXT: [004]     5             {Line}
-; ONE-NEXT: [004]                   {Code} 'store i32 7, ptr %CONSTANT, align 4, !dbg !32'
+; ONE-NEXT: [004]                   {Code} 'store i32 7, ptr %CONSTANT, align 4, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [004]     6             {Line}
-; ONE-NEXT: [004]                   {Code} 'store i32 7, ptr %retval, align 4, !dbg !33'
+; ONE-NEXT: [004]                   {Code} 'store i32 7, ptr %retval, align 4, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [004]     6             {Line}
-; ONE-NEXT: [004]                   {Code} 'br label %return, !dbg !33'
+; ONE-NEXT: [004]                   {Code} 'br label %return, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [003]     2           {Parameter} 'ParamPtr' -> 'INTPTR'
 ; ONE-NEXT: [003]     2           {Parameter} 'ParamUnsigned' -> 'unsigned int'
 ; ONE-NEXT: [003]     2           {Parameter} 'ParamBool' -> 'bool'
@@ -60,19 +60,19 @@
 ; ONE-NEXT: [003]                 {Code} '%storedv = zext i1 %ParamBool to i8'
 ; ONE-NEXT: [003]                 {Code} 'store i8 %storedv, ptr %ParamBool.addr, align 1'
 ; ONE-NEXT: [003]     8           {Line}
-; ONE-NEXT: [003]                 {Code} '%1 = load i32, ptr %ParamUnsigned.addr, align 4, !dbg !34'
+; ONE-NEXT: [003]                 {Code} '%1 = load i32, ptr %ParamUnsigned.addr, align 4, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [003]     8           {Line}
-; ONE-NEXT: [003]                 {Code} 'store i32 %1, ptr %retval, align 4, !dbg !35'
+; ONE-NEXT: [003]                 {Code} 'store i32 %1, ptr %retval, align 4, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [003]     8           {Line}
-; ONE-NEXT: [003]                 {Code} 'br label %return, !dbg !35'
+; ONE-NEXT: [003]                 {Code} 'br label %return, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [003]     9           {Line}
-; ONE-NEXT: [003]                 {Code} '%2 = load i32, ptr %retval, align 4, !dbg !36'
+; ONE-NEXT: [003]                 {Code} '%2 = load i32, ptr %retval, align 4, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [003]     9           {Line}
-; ONE-NEXT: [003]                 {Code} 'ret i32 %2, !dbg !36'
+; ONE-NEXT: [003]                 {Code} 'ret i32 %2, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [003]     3           {Line}
-; ONE-NEXT: [003]                 {Code} '%0 = load i8, ptr %ParamBool.addr, align 1, !dbg !26'
+; ONE-NEXT: [003]                 {Code} '%0 = load i8, ptr %ParamBool.addr, align 1, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [003]     3           {Line}
-; ONE-NEXT: [003]                 {Code} '%loadedv = trunc i8 %0 to i1, !dbg !26'
+; ONE-NEXT: [003]                 {Code} '%loadedv = trunc i8 %0 to i1, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [003]     3           {Line}
-; ONE-NEXT: [003]                 {Code} 'br i1 %loadedv, label %if.then, label %if.end, !dbg !26'
+; ONE-NEXT: [003]                 {Code} 'br i1 %loadedv, label %if.then, label %if.end, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [002]     1         {TypeAlias} 'INTPTR' -> '* const int'
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/IR/01-ir-select-logical-elements.test b/llvm/test/tools/llvm-debuginfo-analyzer/IR/01-ir-select-logical-elements.test
index 51bbb30c1d97e..cae4183e7253f 100644
--- a/llvm/test/tools/llvm-debuginfo-analyzer/IR/01-ir-select-logical-elements.test
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/IR/01-ir-select-logical-elements.test
@@ -30,16 +30,16 @@
 ; ONE-NEXT: [000]           {File} 'test-clang.ll'
 ; ONE-EMPTY:
 ; ONE-NEXT: [001]           {CompileUnit} 'test.cpp'
-; ONE-NEXT: [003]           {Code} '%0 = load i8, ptr %ParamBool.addr, align 1, !dbg !26'
-; ONE-NEXT: [003]           {Code} '%1 = load i32, ptr %ParamUnsigned.addr, align 4, !dbg !34'
-; ONE-NEXT: [003]           {Code} '%2 = load i32, ptr %retval, align 4, !dbg !36'
-; ONE-NEXT: [003]           {Code} '%loadedv = trunc i8 %0 to i1, !dbg !26'
+; ONE-NEXT: [003]           {Code} '%0 = load i8, ptr %ParamBool.addr, align 1, !dbg !{{[0-9]+}}'
+; ONE-NEXT: [003]           {Code} '%1 = load i32, ptr %ParamUnsigned.addr, align 4, !dbg !{{[0-9]+}}'
+; ONE-NEXT: [003]           {Code} '%2 = load i32, ptr %retval, align 4, !dbg !{{[0-9]+}}'
+; ONE-NEXT: [003]           {Code} '%loadedv = trunc i8 %0 to i1, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [003]           {Code} '%storedv = zext i1 %ParamBool to i8'
-; ONE-NEXT: [003]           {Code} 'br i1 %loadedv, label %if.then, label %if.end, !dbg !26'
-; ONE-NEXT: [003]           {Code} 'store i32 %1, ptr %retval, align 4, !dbg !35'
+; ONE-NEXT: [003]           {Code} 'br i1 %loadedv, label %if.then, label %if.end, !dbg !{{[0-9]+}}'
+; ONE-NEXT: [003]           {Code} 'store i32 %1, ptr %retval, align 4, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [003]           {Code} 'store i32 %ParamUnsigned, ptr %ParamUnsigned.addr, align 4'
-; ONE-NEXT: [004]           {Code} 'store i32 7, ptr %CONSTANT, align 4, !dbg !32'
-; ONE-NEXT: [004]           {Code} 'store i32 7, ptr %retval, align 4, !dbg !33'
+; ONE-NEXT: [004]           {Code} 'store i32 7, ptr %CONSTANT, align 4, !dbg !{{[0-9]+}}'
+; ONE-NEXT: [004]           {Code} 'store i32 7, ptr %retval, align 4, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [003]           {Code} 'store i8 %storedv, ptr %ParamBool.addr, align 1'
 ; ONE-NEXT: [003]           {Code} 'store ptr %ParamPtr, ptr %ParamPtr.addr, align 8'
 ; ONE-EMPTY:
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/IR/02-ir-logical-lines.test b/llvm/test/tools/llvm-debuginfo-analyzer/IR/02-ir-logical-lines.test
index 76272e3f677ea..8280d0f41ff6d 100644
--- a/llvm/test/tools/llvm-debuginfo-analyzer/IR/02-ir-logical-lines.test
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/IR/02-ir-logical-lines.test
@@ -33,9 +33,9 @@
 ; ONE-NEXT: [003]                 {Code} '%retval = alloca i32, align 4'
 ; ONE-NEXT: [003]                 {Code} 'store i32 0, ptr %retval, align 4'
 ; ONE-NEXT: [003]     5           {Line}
-; ONE-NEXT: [003]                 {Code} '%call = call noundef i32 (ptr, ...) @_Z6printfPKcz(ptr noundef @.str), !dbg !22'
+; ONE-NEXT: [003]                 {Code} '%call = call noundef i32 (ptr, ...) @_Z6printfPKcz(ptr noundef @.str), !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [003]     6           {Line}
-; ONE-NEXT: [003]                 {Code} 'ret i32 0, !dbg !23'
+; ONE-NEXT: [003]                 {Code} 'ret i32 0, !dbg !{{[0-9]+}}'
 ; ONE-EMPTY:
 ; ONE-NEXT: Logical View:
 ; ONE-NEXT: [000]           {File} 'hello-world-dwarf-clang.o' -> elf64-x86-64
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/IR/06-ir-full-logical-view.test b/llvm/test/tools/llvm-debuginfo-analyzer/IR/06-ir-full-logical-view.test
index 3f6db431a676c..29fc246b27a21 100644
--- a/llvm/test/tools/llvm-debuginfo-analyzer/IR/06-ir-full-logical-view.test
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/IR/06-ir-full-logical-view.test
@@ -51,11 +51,11 @@
 ; ONE-NEXT: [0x0000000000][006]                        {Location}
 ; ONE-NEXT: [0x0000000000][007]                          {Entry} bregx 3 ptr %CONSTANT+0
 ; ONE-NEXT: [0x0000000030][004]      5             {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x0000000030][004]                    {Code} 'store i32 7, ptr %CONSTANT, align 4, !dbg !32'
+; ONE-NEXT: [0x0000000030][004]                    {Code} 'store i32 7, ptr %CONSTANT, align 4, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [0x0000000034][004]      6             {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x0000000034][004]                    {Code} 'store i32 7, ptr %retval, align 4, !dbg !33'
+; ONE-NEXT: [0x0000000034][004]                    {Code} 'store i32 7, ptr %retval, align 4, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [0x0000000038][004]      6             {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x0000000038][004]                    {Code} 'br label %return, !dbg !33'
+; ONE-NEXT: [0x0000000038][004]                    {Code} 'br label %return, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [0x0000000014][003]      2           {Parameter} 'ParamPtr' -> [0x0000000028]'INTPTR'
 ; ONE-NEXT: [0x0000000014][004]                    {Coverage} 100.00%
 ; ONE-NEXT: [0x0000000000][004]                    {Location}
@@ -80,21 +80,21 @@
 ; ONE-NEXT: [0x000000001c][003]                  {Code} '%storedv = zext i1 %ParamBool to i8'
 ; ONE-NEXT: [0x0000000020][003]                  {Code} 'store i8 %storedv, ptr %ParamBool.addr, align 1'
 ; ONE-NEXT: [0x000000003c][003]      8           {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x000000003c][003]                  {Code} '%1 = load i32, ptr %ParamUnsigned.addr, align 4, !dbg !34'
+; ONE-NEXT: [0x000000003c][003]                  {Code} '%1 = load i32, ptr %ParamUnsigned.addr, align 4, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [0x0000000040][003]      8           {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x0000000040][003]                  {Code} 'store i32 %1, ptr %retval, align 4, !dbg !35'
+; ONE-NEXT: [0x0000000040][003]                  {Code} 'store i32 %1, ptr %retval, align 4, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [0x0000000044][003]      8           {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x0000000044][003]                  {Code} 'br label %return, !dbg !35'
+; ONE-NEXT: [0x0000000044][003]                  {Code} 'br label %return, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [0x0000000048][003]      9           {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x0000000048][003]                  {Code} '%2 = load i32, ptr %retval, align 4, !dbg !36'
+; ONE-NEXT: [0x0000000048][003]                  {Code} '%2 = load i32, ptr %retval, align 4, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [0x000000004c][003]      9           {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x000000004c][003]                  {Code} 'ret i32 %2, !dbg !36'
+; ONE-NEXT: [0x000000004c][003]                  {Code} 'ret i32 %2, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [0x0000000024][003]      3           {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x0000000024][003]                  {Code} '%0 = load i8, ptr %ParamBool.addr, align 1, !dbg !26'
+; ONE-NEXT: [0x0000000024][003]                  {Code} '%0 = load i8, ptr %ParamBool.addr, align 1, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [0x0000000028][003]      3           {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x0000000028][003]                  {Code} '%loadedv = trunc i8 %0 to i1, !dbg !26'
+; ONE-NEXT: [0x0000000028][003]                  {Code} '%loadedv = trunc i8 %0 to i1, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [0x000000002c][003]      3           {Line} '{{.*}}/general/test.cpp'
-; ONE-NEXT: [0x000000002c][003]                  {Code} 'br i1 %loadedv, label %if.then, label %if.end, !dbg !26'
+; ONE-NEXT: [0x000000002c][003]                  {Code} 'br i1 %loadedv, label %if.then, label %if.end, !dbg !{{[0-9]+}}'
 ; ONE-NEXT: [0x0000000024][002]                {BaseType} 'int'
 ; ONE-NEXT: [0x0000000028][002]      1         {TypeAlias} 'INTPTR' -> [0x000000002c]'* const int'
 ; ONE-NEXT: [0x0000000034][002]                {BaseType} 'unsigned int'
diff --git a/llvm/tools/llvm-dis/llvm-dis.cpp b/llvm/tools/llvm-dis/llvm-dis.cpp
index a961f9cb0f7dd..2a986fc145fbf 100644
--- a/llvm/tools/llvm-dis/llvm-dis.cpp
+++ b/llvm/tools/llvm-dis/llvm-dis.cpp
@@ -263,6 +263,7 @@ int main(int argc, char **argv) {
       // All that llvm-dis does is write the assembly to a file.
       if (!DontPrint) {
         if (M) {
+          M->renumberMetadataForAssembly();
           M->print(Out->os(), Annotator.get(),
                    /* ShouldPreserveUseListOrder */ false);
         }
diff --git a/llvm/tools/llvm-extract/llvm-extract.cpp b/llvm/tools/llvm-extract/llvm-extract.cpp
index 439a4a48b350a..17ce664a64ba2 100644
--- a/llvm/tools/llvm-extract/llvm-extract.cpp
+++ b/llvm/tools/llvm-extract/llvm-extract.cpp
@@ -411,8 +411,10 @@ int main(int argc, char **argv) {
   }
 
   if (OutputAssembly)
-    PM.addPass(
-        PrintModulePass(Out.os(), "", /* ShouldPreserveUseListOrder */ false));
+    PM.addPass(PrintModulePass(Out.os(), "",
+                               /*ShouldPreserveUseListOrder=*/false,
+                               /*EmitSummaryIndex=*/false,
+                               /*ShouldRenumberMetadata=*/true));
   else if (Force || !CheckBitcodeOutputToConsole(Out.os()))
     PM.addPass(
         BitcodeWriterPass(Out.os(), /* ShouldPreserveUseListOrder */ true));
diff --git a/llvm/tools/llvm-link/llvm-link.cpp b/llvm/tools/llvm-link/llvm-link.cpp
index e49082f2d7bfb..9390301f1b75a 100644
--- a/llvm/tools/llvm-link/llvm-link.cpp
+++ b/llvm/tools/llvm-link/llvm-link.cpp
@@ -518,6 +518,7 @@ int main(int argc, char **argv) {
   if (Verbose)
     errs() << "Writing bitcode...\n";
   if (OutputAssembly) {
+    Composite->renumberMetadataForAssembly();
     Composite->print(Out.os(), nullptr, /* ShouldPreserveUseListOrder */ false);
   } else if (Force || !CheckBitcodeOutputToConsole(Out.os())) {
     WriteBitcodeToFile(*Composite, Out.os(),
diff --git a/llvm/tools/llvm-reduce/ReducerWorkItem.cpp b/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
index fa4da7a073f1e..c483a7ef893e0 100644
--- a/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
+++ b/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
@@ -20,6 +20,7 @@
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineJumpTableInfo.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineModuleSlotTracker.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/PseudoSourceValueManager.h"
 #include "llvm/CodeGen/TargetInstrInfo.h"
@@ -443,12 +444,18 @@ static std::unique_ptr<MachineFunction> cloneMF(MachineFunction *SrcMF,
 
 void ReducerWorkItem::print(raw_ostream &ROS, void *p) const {
   if (MMI) {
+    M->renumberMetadataForAssembly();
     printMIR(ROS, *M);
     for (Function &F : *M) {
-      if (auto *MF = MMI->getMachineFunction(F))
+      if (auto *MF = MMI->getMachineFunction(F)) {
+        MachineModuleSlotTracker MST(
+            [&](const Function &F) { return MMI->getMachineFunction(F); }, MF);
+        MST.renumberMetadataForAssembly();
         printMIR(ROS, *MMI, *MF);
+      }
     }
   } else {
+    M->renumberMetadataForAssembly();
     M->print(ROS, /*AssemblyAnnotationWriter=*/nullptr,
              /*ShouldPreserveUseListOrder=*/true);
   }
diff --git a/llvm/tools/llvm-split/llvm-split.cpp b/llvm/tools/llvm-split/llvm-split.cpp
index e7c9d52127274..4ead6fd4b88be 100644
--- a/llvm/tools/llvm-split/llvm-split.cpp
+++ b/llvm/tools/llvm-split/llvm-split.cpp
@@ -116,7 +116,7 @@ void writeStringToFile(StringRef Content, StringRef Path) {
   OS << Content << "\n";
 }
 
-void writeModuleToFile(const Module &M, StringRef Path, bool OutputAssembly) {
+void writeModuleToFile(Module &M, StringRef Path, bool OutputAssembly) {
   int FD = -1;
   if (std::error_code EC = sys::fs::openFileForWrite(Path, FD)) {
     errs() << formatv("error opening file: {0}, error: {1}", Path, EC.message())
@@ -125,9 +125,10 @@ void writeModuleToFile(const Module &M, StringRef Path, bool OutputAssembly) {
   }
 
   raw_fd_ostream OS(FD, /*ShouldClose*/ true);
-  if (OutputAssembly)
+  if (OutputAssembly) {
+    M.renumberMetadataForAssembly();
     M.print(OS, /*AssemblyAnnotationWriter*/ nullptr);
-  else
+  } else
     WriteBitcodeToFile(M, OS);
 }
 
diff --git a/llvm/tools/llvm-stress/llvm-stress.cpp b/llvm/tools/llvm-stress/llvm-stress.cpp
index e3c8a5c3d51ab..e99c83c2b9bac 100644
--- a/llvm/tools/llvm-stress/llvm-stress.cpp
+++ b/llvm/tools/llvm-stress/llvm-stress.cpp
@@ -754,6 +754,7 @@ int main(int argc, char **argv) {
     report_fatal_error("Broken module found, compilation aborted!");
 
   // Output textual IR.
+  M->renumberMetadataForAssembly();
   M->print(Out->os(), nullptr);
 
   Out->keep();
diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp
index 04c7b99e08cbc..4fbaf02526a87 100644
--- a/llvm/tools/opt/NewPMDriver.cpp
+++ b/llvm/tools/opt/NewPMDriver.cpp
@@ -529,7 +529,8 @@ bool llvm::runPassPipeline(
       MPM.addPass(AssignGUIDPass());
     }
     MPM.addPass(PrintModulePass(
-        Out->os(), "", ShouldPreserveAssemblyUseListOrder, EmitSummaryIndex));
+        Out->os(), "", ShouldPreserveAssemblyUseListOrder, EmitSummaryIndex,
+        /*ShouldRenumberMetadata=*/true));
     break;
   case OK_OutputBitcode:
     if (EmitSummaryIndex) {
diff --git a/llvm/tools/opt/optdriver.cpp b/llvm/tools/opt/optdriver.cpp
index 2db4502aa449b..5333825629a27 100644
--- a/llvm/tools/opt/optdriver.cpp
+++ b/llvm/tools/opt/optdriver.cpp
@@ -930,10 +930,11 @@ optMain(int argc, char **argv,
       BOS = std::make_unique<raw_svector_ostream>(Buffer);
       OS = BOS.get();
     }
-    if (OutputAssembly)
+    if (OutputAssembly) {
       Passes.add(createPrintModulePass(
-          *OS, "", /* ShouldPreserveAssemblyUseListOrder */ false));
-    else
+          *OS, "", /*ShouldPreserveAssemblyUseListOrder=*/false,
+          /*ShouldRenumberMetadata=*/true));
+    } else
       Passes.add(createBitcodeWriterPass(
           *OS, /* ShouldPreserveBitcodeUseListOrder */ true));
   }
diff --git a/llvm/tools/verify-uselistorder/verify-uselistorder.cpp b/llvm/tools/verify-uselistorder/verify-uselistorder.cpp
index 8f58cc00a3dd1..95edf41e84ce4 100644
--- a/llvm/tools/verify-uselistorder/verify-uselistorder.cpp
+++ b/llvm/tools/verify-uselistorder/verify-uselistorder.cpp
@@ -75,7 +75,7 @@ struct TempFile {
   FileRemover Remover;
   bool init(const std::string &Ext, bool IsText = false);
   bool writeBitcode(const Module &M) const;
-  bool writeAssembly(const Module &M) const;
+  bool writeAssembly(Module &M) const;
   std::unique_ptr<Module> readBitcode(LLVMContext &Context) const;
   std::unique_ptr<Module> readAssembly(LLVMContext &Context) const;
 };
@@ -137,7 +137,7 @@ bool TempFile::writeBitcode(const Module &M) const {
   return false;
 }
 
-bool TempFile::writeAssembly(const Module &M) const {
+bool TempFile::writeAssembly(Module &M) const {
   LLVM_DEBUG(dbgs() << " - write assembly\n");
   std::error_code EC;
   raw_fd_ostream OS(Filename, EC, sys::fs::OF_TextWithCRLF);
@@ -146,6 +146,7 @@ bool TempFile::writeAssembly(const Module &M) const {
     return true;
   }
 
+  M.renumberMetadataForAssembly();
   M.print(OS, nullptr, /* ShouldPreserveUseListOrder */ true);
   return false;
 }
@@ -379,7 +380,7 @@ static void verifyBitcodeUseListOrder(const Module &M) {
   verifyAfterRoundTrip(M, F.readBitcode(Context));
 }
 
-static void verifyAssemblyUseListOrder(const Module &M) {
+static void verifyAssemblyUseListOrder(Module &M) {
   TempFile F;
   if (F.init("ll", /*IsText=*/true))
     report_fatal_error("failed to initialize assembly file");
@@ -391,7 +392,7 @@ static void verifyAssemblyUseListOrder(const Module &M) {
   verifyAfterRoundTrip(M, F.readAssembly(Context));
 }
 
-static void verifyUseListOrder(const Module &M) {
+static void verifyUseListOrder(Module &M) {
   outs() << "verify bitcode\n";
   verifyBitcodeUseListOrder(M);
   outs() << "verify assembly\n";
diff --git a/llvm/unittests/AsmParser/AsmParserTest.cpp b/llvm/unittests/AsmParser/AsmParserTest.cpp
index bdfd91dbec269..631cbe5c56464 100644
--- a/llvm/unittests/AsmParser/AsmParserTest.cpp
+++ b/llvm/unittests/AsmParser/AsmParserTest.cpp
@@ -16,10 +16,12 @@
 #include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
+#include "llvm/IR/ModuleSummaryIndex.h"
 #include "llvm/IR/Value.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/raw_ostream.h"
 #include "gtest/gtest.h"
 
 #define DEBUG_TYPE "unittest-asm-parser-tests"
@@ -73,6 +75,37 @@ TEST(AsmParserTest, SlotMappingTest) {
   EXPECT_EQ(Mapping.MetadataNodes.count(1), 0u);
 }
 
+TEST(AsmParserTest, ParsingPreservesMetadataIDsInOtherModules) {
+  StringRef Source = "!named = !{!0}\n!0 = distinct !{}\n";
+
+  for (bool WithIndex : {false, true}) {
+    SCOPED_TRACE(WithIndex ? "parseAssemblyWithIndex" : "parseAssembly");
+    LLVMContext Ctx;
+    SMDiagnostic Error;
+    auto Mod1 = parseAssemblyString(Source, Error, Ctx);
+    ASSERT_TRUE(Mod1) << Error.getMessage().str();
+    MDNode *Node = Mod1->getNamedMetadata("named")->getOperand(0);
+
+    auto PrintMetadataID = [&] {
+      std::string ID;
+      raw_string_ostream OS(ID);
+      Node->printAsOperand(OS, Mod1.get());
+      return ID;
+    };
+    std::string ID = PrintMetadataID();
+
+    std::unique_ptr<Module> Mod2;
+    if (WithIndex)
+      Mod2 = parseAssemblyWithIndex(MemoryBufferRef(Source, "<string>"), Error,
+                                    Ctx)
+                 .Mod;
+    else
+      Mod2 = parseAssemblyString(Source, Error, Ctx);
+    ASSERT_TRUE(Mod2) << Error.getMessage().str();
+    EXPECT_EQ(ID, PrintMetadataID());
+  }
+}
+
 TEST(AsmParserTest, TypeAndConstantValueParsing) {
   LLVMContext Ctx;
   SMDiagnostic Error;
diff --git a/llvm/unittests/IR/AsmWriterTest.cpp b/llvm/unittests/IR/AsmWriterTest.cpp
index 75305f4e2dea4..6c04309af810e 100644
--- a/llvm/unittests/IR/AsmWriterTest.cpp
+++ b/llvm/unittests/IR/AsmWriterTest.cpp
@@ -5,6 +5,7 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
+#include "llvm/AsmParser/Parser.h"
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/Function.h"
@@ -12,6 +13,7 @@
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/MDBuilder.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Support/SourceMgr.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
@@ -62,6 +64,128 @@ TEST(AsmWriterTest, DumpDIExpression) {
   EXPECT_EQ("!DIExpression(DW_OP_constu, 4, DW_OP_minus, DW_OP_deref)", S);
 }
 
+TEST(AsmWriterTest, PersistentBasicBlockPrint) {
+  LLVMContext Ctx;
+  SMDiagnostic Err;
+  std::unique_ptr<Module> M = parseAssemblyString(R"(
+    @0 = global i32 0
+
+    declare void @use(ptr)
+
+    define void @f() !dbg !6 {
+      call void @use(ptr @0), !annotation !12
+        #dbg_value(i32 0, !9, !DIExpression(DW_OP_constu, 4), !11)
+      ret void, !annotation !12
+    }
+
+    define void @g() {
+      ret void
+    }
+
+    !llvm.dbg.cu = !{!0}
+    !llvm.module.flags = !{!5}
+
+    !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "test", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+    !1 = !DIFile(filename: "t.ll", directory: "/")
+    !2 = !{}
+    !5 = !{i32 2, !"Debug Info Version", i32 3}
+    !6 = distinct !DISubprogram(name: "f", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
+    !7 = !DISubroutineType(types: !2)
+    !8 = !{!9}
+    !9 = !DILocalVariable(name: "x", scope: !6, file: !1, line: 1, type: !10)
+    !10 = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_unsigned)
+    !11 = !DILocation(line: 1, column: 1, scope: !6)
+    !12 = !{!"annotation"}
+  )",
+                                                  Err, Ctx);
+  ASSERT_NE(M, nullptr);
+
+  std::string First;
+  raw_string_ostream FirstOS(First);
+  M->getFunction("f")->getEntryBlock().print(FirstOS);
+
+  std::string Second;
+  raw_string_ostream SecondOS(Second);
+  M->getFunction("f")->getEntryBlock().print(SecondOS);
+
+  EXPECT_EQ(First, Second);
+  EXPECT_THAT(First, HasSubstr("call void @use(ptr @0), !annotation !"));
+  EXPECT_THAT(First, HasSubstr("#dbg_value(i32 0, !"));
+  EXPECT_THAT(First, HasSubstr("!DIExpression(DW_OP_constu, 4)"));
+  EXPECT_THAT(First, HasSubstr("ret void, !annotation !"));
+
+  MDNode *Earlier = MDNode::getDistinct(Ctx, MDString::get(Ctx, "earlier"));
+  M->getFunction("f")->getEntryBlock().getTerminator()->setMetadata("order",
+                                                                    Earlier);
+  MDNode *Later = MDNode::getDistinct(Ctx, MDString::get(Ctx, "later"));
+  M->getFunction("g")->getEntryBlock().getTerminator()->setMetadata("order",
+                                                                    Later);
+
+  std::string LaterOutput;
+  raw_string_ostream LaterOS(LaterOutput);
+  M->getFunction("g")->getEntryBlock().print(LaterOS);
+
+  std::string EarlierOutput;
+  raw_string_ostream EarlierOS(EarlierOutput);
+  M->getFunction("f")->getEntryBlock().print(EarlierOS);
+
+  StringRef MetadataPrefix = "!order !";
+  size_t EarlierPos = EarlierOutput.find(MetadataPrefix);
+  size_t LaterPos = LaterOutput.find(MetadataPrefix);
+  ASSERT_NE(EarlierPos, StringRef::npos);
+  ASSERT_NE(LaterPos, StringRef::npos);
+  StringRef EarlierIDText =
+      StringRef(EarlierOutput).drop_front(EarlierPos + MetadataPrefix.size());
+  StringRef LaterIDText =
+      StringRef(LaterOutput).drop_front(LaterPos + MetadataPrefix.size());
+  unsigned EarlierID;
+  unsigned LaterID;
+  ASSERT_FALSE(EarlierIDText.consumeInteger(10, EarlierID));
+  ASSERT_FALSE(LaterIDText.consumeInteger(10, LaterID));
+  EXPECT_LT(EarlierID, LaterID);
+}
+
+TEST(AsmWriterTest, PersistentPrintTemporaryMetadata) {
+  LLVMContext Ctx;
+  Module M("test", Ctx);
+  Function *F = Function::Create(
+      FunctionType::get(Type::getVoidTy(Ctx), /*isVarArg=*/false),
+      Function::ExternalLinkage, "f", M);
+  BasicBlock *BB = BasicBlock::Create(Ctx, "entry", F);
+  ReturnInst *Ret = ReturnInst::Create(Ctx, BB);
+
+  MDNode *Permanent = MDNode::getDistinct(Ctx, MDString::get(Ctx, "permanent"));
+  TempMDNode Temporary = MDNode::getTemporary(Ctx, Permanent);
+  Ret->setMetadata("permanent", Permanent);
+  Ret->setMetadata("temporary", Temporary.get());
+
+  std::string FunctionText;
+  raw_string_ostream FunctionOS(FunctionText);
+  F->print(FunctionOS);
+  EXPECT_THAT(FunctionText, HasSubstr("!permanent !0"));
+  EXPECT_THAT(FunctionText, HasSubstr("!temporary !1"));
+
+  std::string BasicBlockText;
+  raw_string_ostream BasicBlockOS(BasicBlockText);
+  BB->print(BasicBlockOS);
+  EXPECT_THAT(BasicBlockText, HasSubstr("!permanent !0"));
+  EXPECT_THAT(BasicBlockText, HasSubstr("!temporary !1"));
+
+  std::string ModuleText;
+  raw_string_ostream ModuleOS(ModuleText);
+  M.print(ModuleOS, nullptr);
+  EXPECT_THAT(ModuleText, HasSubstr("!0 = distinct !{!\"permanent\"}"));
+  EXPECT_THAT(ModuleText, HasSubstr("!1 = <temporary!> !{!0}"));
+
+  MDNode *Later = MDNode::getDistinct(Ctx, MDString::get(Ctx, "later"));
+  Ret->setMetadata("later", Later);
+  std::string LaterText;
+  raw_string_ostream LaterOS(LaterText);
+  F->print(LaterOS);
+  EXPECT_THAT(LaterText, HasSubstr("!later !2"));
+  EXPECT_THAT(LaterText, HasSubstr("!temporary !1"));
+}
+
 TEST(AsmWriterTest, PrintAddrspaceWithNullOperand) {
   LLVMContext Ctx;
   Module M("test module", Ctx);
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index f2c55c0f2a534..5f6feb5bd87bb 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -282,15 +282,11 @@ TEST_F(MDNodeTest, Print) {
   std::string Expected;
   {
     raw_string_ostream OS(Expected);
-    OS << "<" << (void *)N << "> = !{";
+    OS << "!3 = !{";
     C->printAsOperand(OS);
     OS << ", ";
     S->printAsOperand(OS);
-    OS << ", null";
-    MDNode *Nodes[] = {N0, N1, N2};
-    for (auto *Node : Nodes)
-      OS << ", <" << (void *)Node << ">";
-    OS << "}";
+    OS << ", null, !0, !1, !2}";
   }
 
   std::string Actual;
@@ -319,9 +315,9 @@ TEST_F(MDNodeTest, PrintTemporary) {
   NamedMDNode *NMD = M.getOrInsertNamedMetadata("named");
   NMD->addOperand(N);
 
-  EXPECT_PRINTER_EQ("!0 = !{!1}", N->print(OS, &M));
-  EXPECT_PRINTER_EQ("!1 = <temporary!> !{!2}", Temp->print(OS, &M));
-  EXPECT_PRINTER_EQ("!2 = !{}", Arg->print(OS, &M));
+  EXPECT_PRINTER_EQ("!2 = !{!1}", N->print(OS, &M));
+  EXPECT_PRINTER_EQ("!1 = <temporary!> !{!0}", Temp->print(OS, &M));
+  EXPECT_PRINTER_EQ("!0 = !{}", Arg->print(OS, &M));
 
   // Cleanup.
   Temp->replaceAllUsesWith(Arg);
@@ -343,11 +339,11 @@ TEST_F(MDNodeTest, PrintFromModule) {
   std::string Expected;
   {
     raw_string_ostream OS(Expected);
-    OS << "!0 = !{";
+    OS << "!3 = !{";
     C->printAsOperand(OS);
     OS << ", ";
     S->printAsOperand(OS);
-    OS << ", null, !1, !2, !3}";
+    OS << ", null, !0, !1, !2}";
   }
 
   EXPECT_PRINTER_EQ(Expected, N->print(OS, &M));
diff --git a/llvm/unittests/IR/ModuleTest.cpp b/llvm/unittests/IR/ModuleTest.cpp
index e8c2ecfb9f3a8..82e652aadc013 100644
--- a/llvm/unittests/IR/ModuleTest.cpp
+++ b/llvm/unittests/IR/ModuleTest.cpp
@@ -438,6 +438,7 @@ define void @Foo2() {
       ASSERT_EQ(NMD.getParent(), &*M1);
   }
 
+  M1->renumberMetadataForAssembly();
   std::string M1Print;
   {
     llvm::raw_string_ostream Os(M1Print);
@@ -446,6 +447,60 @@ define void @Foo2() {
   ASSERT_EQ(M2Str, M1Print);
 }
 
+TEST(ModuleTest, RenumberMetadataPreservesContextWideUniqueIDs) {
+  LLVMContext Context;
+  Module M("M", Context);
+  MDNode *Detached =
+      MDNode::getDistinct(Context, MDString::get(Context, "detached"));
+  MDNode *Attached =
+      MDNode::getDistinct(Context, MDString::get(Context, "attached"));
+  NamedMDNode *NMD = M.getOrInsertNamedMetadata("n");
+  NMD->addOperand(Attached);
+
+  M.renumberMetadataForAssembly();
+  NMD->addOperand(Detached);
+
+  std::string Assembly;
+  raw_string_ostream OS(Assembly);
+  M.print(OS, nullptr);
+  EXPECT_NE(Assembly.find("!n = !{!0, !2}"), std::string::npos);
+
+  LLVMContext ParsedContext;
+  SMDiagnostic Err;
+  EXPECT_TRUE(parseAssemblyString(Assembly, Err, ParsedContext))
+      << Err.getMessage().str();
+}
+
+TEST(ModuleTest, RenumberMetadataPreservesUniqueTemporaryIDs) {
+  LLVMContext Context;
+  Module M("M", Context);
+  TempMDTuple DetachedA =
+      MDTuple::getTemporary(Context, MDString::get(Context, "detached-a"));
+  TempMDTuple DetachedB =
+      MDTuple::getTemporary(Context, MDString::get(Context, "detached-b"));
+  MDNode *AttachedA =
+      MDNode::getDistinct(Context, MDString::get(Context, "attached-a"));
+  MDNode *AttachedB =
+      MDNode::getDistinct(Context, MDString::get(Context, "attached-b"));
+  NamedMDNode *NMD = M.getOrInsertNamedMetadata("n");
+  NMD->addOperand(AttachedA);
+  NMD->addOperand(AttachedB);
+
+  M.renumberMetadataForAssembly();
+  NMD->addOperand(MDNode::replaceWithDistinct(std::move(DetachedA)));
+  NMD->addOperand(MDNode::replaceWithDistinct(std::move(DetachedB)));
+
+  std::string Assembly;
+  raw_string_ostream OS(Assembly);
+  M.print(OS, nullptr);
+  EXPECT_NE(Assembly.find("!n = !{!0, !1, !4, !5}"), std::string::npos);
+
+  LLVMContext ParsedContext;
+  SMDiagnostic Err;
+  EXPECT_TRUE(parseAssemblyString(Assembly, Err, ParsedContext))
+      << Err.getMessage().str();
+}
+
 TEST(ModuleTest, FunctionDefinitions) {
   // Test getFunctionDefs() method which returns only functions with bodies
   LLVMContext Context;
diff --git a/llvm/unittests/MIR/MachineMetadata.cpp b/llvm/unittests/MIR/MachineMetadata.cpp
index 242c14a36a707..c611cf062bf6b 100644
--- a/llvm/unittests/MIR/MachineMetadata.cpp
+++ b/llvm/unittests/MIR/MachineMetadata.cpp
@@ -19,6 +19,7 @@
 #include "llvm/CodeGen/TargetLowering.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/FileCheck/FileCheck.h"
+#include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/MDBuilder.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/ModuleSlotTracker.h"
@@ -49,20 +50,9 @@ class MachineMetadataTest : public testing::Test {
   void SetUp() override { M = std::make_unique<Module>("Dummy", Context); }
 
   void addHooks(ModuleSlotTracker &MST, const MachineOperand &MO) {
-    // Setup hooks to assign slot numbers for the specified machine metadata.
-    MST.setProcessHook([&MO](AbstractSlotTrackerStorage *AST, const Module *M,
-                             bool ShouldInitializeAllMetadata) {
-      if (ShouldInitializeAllMetadata) {
-        if (MO.isMetadata())
-          AST->createMetadataSlot(MO.getMetadata());
-      }
-    });
-    MST.setProcessHook([&MO](AbstractSlotTrackerStorage *AST, const Function *F,
-                             bool ShouldInitializeAllMetadata) {
-      if (!ShouldInitializeAllMetadata) {
-        if (MO.isMetadata())
-          AST->createMetadataSlot(MO.getMetadata());
-      }
+    MST.setProcessHook([&MO](AbstractSlotTrackerStorage *AST, const Module *) {
+      if (MO.isMetadata())
+        AST->createMetadataSlot(MO.getMetadata());
     });
   }
 
@@ -140,9 +130,7 @@ TEST_F(MachineMetadataTest, TrivialHook) {
 }
 
 TEST_F(MachineMetadataTest, BasicHook) {
-  // Verify that post-process hook is invoked to assign slot numbers for
-  // machine metadata. When both LLVM IR and machine IR contain metadata,
-  // ensure that machine metadata is always assigned after LLVM IR.
+  // Verify that the post-process hook records machine metadata.
   ASSERT_TRUE(M);
 
   // Create a MachineOperand with a metadata and print it.
@@ -165,16 +153,16 @@ TEST_F(MachineMetadataTest, BasicHook) {
   addHooks(MST, MO);
 
   // Print a MachineOperand containing a metadata node.
-  EXPECT_EQ("!1", print([&](raw_ostream &OS) {
+  EXPECT_EQ("!0", print([&](raw_ostream &OS) {
               MO.print(OS, MST, LLT{}, /*OpIdx*/ ~0U, /*PrintDef=*/false,
                        /*IsStandalone=*/false,
                        /*ShouldPrintRegisterTies=*/false, /*TiedOperandIdx=*/0,
                        /*TRI=*/nullptr);
             }));
   // Print the definition of these unnamed metadata nodes.
-  EXPECT_EQ("!0 = !{!\"bar\"}",
+  EXPECT_EQ("!1 = !{!\"bar\"}",
             print([&](raw_ostream &OS) { Node->print(OS, MST); }));
-  EXPECT_EQ("!1 = !{!\"foo\"}",
+  EXPECT_EQ("!0 = !{!\"foo\"}",
             print([&](raw_ostream &OS) { MachineNode->print(OS, MST); }));
 }
 
@@ -252,10 +240,9 @@ body:             |
 
   MachineModuleSlotTracker MST(
       [&](const Function &F) { return MMI.getMachineFunction(F); }, MF);
-  // Print that MI with new machine metadata, which slot numbers should be
-  // assigned.
+  // Print the MI using the stored IDs of the new machine metadata.
   EXPECT_EQ("%1:gpr32 = LDRWui %0, 0 :: (load (s32) from %ir.p, "
-            "!alias.scope !0, !noalias !3)",
+            "!alias.scope !3, !noalias !4)",
             print([&](raw_ostream &OS) {
               MI.print(OS, MST, /*IsStandalone=*/false, /*SkipOpers=*/false,
                        /*SkipDebugLoc=*/false, /*AddNewLine=*/false);
@@ -342,10 +329,64 @@ body:             |
   auto *MF = MMI.getMachineFunction(*M->getFunction("test0"));
   auto *MBB = MF->getBlockNumbered(0);
 
+  MachineInstr *DbgValue = nullptr;
   for (auto It = MBB->begin(); It != MBB->end(); ++It) {
     MachineInstr &MI = *It;
     ASSERT_TRUE(MI.isMetaInstruction());
+    if (MI.isDebugValue())
+      DbgValue = &MI;
   }
+
+  ASSERT_NE(DbgValue, nullptr);
+  auto *IRVar = cast<DILocalVariable>(DbgValue->getOperand(2).getMetadata());
+  M->getOrInsertNamedMetadata("test.ir.variable")
+      ->addOperand(const_cast<DILocalVariable *>(IRVar));
+  // Leave gaps between reachable nodes to exercise sparse metadata IDs.
+  auto *UnusedModuleNode = MDNode::getDistinct(Context, {});
+  (void)UnusedModuleNode;
+  auto *ModuleNode =
+      MDNode::getDistinct(Context, MDString::get(Context, "module metadata"));
+  M->getOrInsertNamedMetadata("test.module.metadata")->addOperand(ModuleNode);
+  auto PrintMetadataID = [&](const MDNode *N) {
+    return print([&](raw_ostream &OS) { N->printAsOperand(OS, M.get()); });
+  };
+  std::string ModuleNodeID = PrintMetadataID(ModuleNode);
+  print([&](raw_ostream &OS) { printMIR(OS, *M); });
+  EXPECT_EQ(ModuleNodeID, PrintMetadataID(ModuleNode));
+
+  auto *UnusedMachineNode = MDNode::getDistinct(Context, {});
+  (void)UnusedMachineNode;
+  auto *MachineLoc =
+      DILocation::get(Context, 2, 1, DbgValue->getDebugLoc()->getScope());
+  auto *MachineNode =
+      MDNode::get(Context, {MDString::get(Context, "machine"), MachineLoc});
+  MBB->front().addOperand(*MF, MachineOperand::CreateMetadata(MachineNode));
+  auto *InlineMachineLoc =
+      DILocation::get(Context, 3, 1, DbgValue->getDebugLoc()->getScope());
+  DbgValue->setDebugLoc(DebugLoc(InlineMachineLoc));
+
+  MachineModuleSlotTracker MST(
+      [&](const Function &F) { return MMI.getMachineFunction(F); }, MF);
+  MachineModuleSlotTracker::MachineMDNodeListType MDList;
+  MST.collectMachineMDNodes(MDList);
+  EXPECT_TRUE(llvm::any_of(
+      MDList, [&](const auto &MD) { return MD.second == MachineNode; }));
+  EXPECT_TRUE(llvm::any_of(
+      MDList, [&](const auto &MD) { return MD.second == MachineLoc; }));
+  EXPECT_FALSE(llvm::any_of(
+      MDList, [&](const auto &MD) { return MD.second == InlineMachineLoc; }));
+  EXPECT_FALSE(
+      llvm::any_of(MDList, [&](const auto &MD) { return MD.second == IRVar; }));
+
+  std::string MachineNodeID = PrintMetadataID(MachineNode);
+  std::string Output = print([&](raw_ostream &OS) {
+    printMIR(OS, *M);
+    printMIR(OS, MMI, *MF);
+  });
+  EXPECT_EQ(ModuleNodeID, PrintMetadataID(ModuleNode));
+  EXPECT_EQ(MachineNodeID, PrintMetadataID(MachineNode));
+  MachineModuleInfo RoundTripMMI(TM.get());
+  EXPECT_TRUE(parseMIR(*TM, Output, RoundTripMMI)) << Output;
 }
 
 TEST_F(MachineMetadataTest, MMSlotTrackerX64) {
@@ -403,11 +444,15 @@ body:             |
 
   MachineModuleSlotTracker MST(
       [&](const Function &F) { return MMI.getMachineFunction(F); }, MF);
-  // Print that MI with new machine metadata, which slot numbers should be
-  // assigned.
+  // Print the MI using the stored IDs of the new machine metadata.
+  std::string Set0ID =
+      print([&](raw_ostream &OS) { Set0->printAsOperand(OS, M.get()); });
+  std::string Set1ID =
+      print([&](raw_ostream &OS) { Set1->printAsOperand(OS, M.get()); });
   EXPECT_EQ(
       "%1:gr32 = MOV32rm %0, 1, $noreg, 0, $noreg :: (load (s32) from %ir.p, "
-      "!alias.scope !0, !noalias !3)",
+      "!alias.scope " +
+          Set0ID + ", !noalias " + Set1ID + ")",
       print([&](raw_ostream &OS) {
         MI.print(OS, MST, /*IsStandalone=*/false, /*SkipOpers=*/false,
                  /*SkipDebugLoc=*/false, /*AddNewLine=*/false);
@@ -503,11 +548,15 @@ body:             |
 
   MachineModuleSlotTracker MST(
       [&](const Function &F) { return MMI.getMachineFunction(F); }, MF);
-  // Print that MI with new machine metadata, which slot numbers should be
-  // assigned.
+  // Print the MI using the stored IDs of the new machine metadata.
+  std::string Set0ID =
+      print([&](raw_ostream &OS) { Set0->printAsOperand(OS, M.get()); });
+  std::string Set1ID =
+      print([&](raw_ostream &OS) { Set1->printAsOperand(OS, M.get()); });
   EXPECT_EQ(
       "%5:vgpr_32 = FLAT_LOAD_DWORD killed %4, 0, 0, implicit $exec, implicit "
-      "$flat_scr :: (load (s32) from %ir.p, !alias.scope !0, !noalias !3)",
+      "$flat_scr :: (load (s32) from %ir.p, !alias.scope " +
+          Set0ID + ", !noalias " + Set1ID + ")",
       print([&](raw_ostream &OS) {
         MI.print(OS, MST, /*IsStandalone=*/false, /*SkipOpers=*/false,
                  /*SkipDebugLoc=*/false, /*AddNewLine=*/false);
diff --git a/mlir/lib/Target/LLVMIR/ConvertToLLVMIR.cpp b/mlir/lib/Target/LLVMIR/ConvertToLLVMIR.cpp
index fef191a302ac8..1797efec0252f 100644
--- a/mlir/lib/Target/LLVMIR/ConvertToLLVMIR.cpp
+++ b/mlir/lib/Target/LLVMIR/ConvertToLLVMIR.cpp
@@ -31,6 +31,7 @@ void registerToLLVMIRTranslation() {
         if (!llvmModule)
           return failure();
 
+        llvmModule->renumberMetadataForAssembly();
         llvmModule->print(output, nullptr);
         return success();
       },
diff --git a/mlir/test/Target/LLVMIR/Import/import-failure.ll b/mlir/test/Target/LLVMIR/Import/import-failure.ll
index 7b59f91497120..ba854d8616144 100644
--- a/mlir/test/Target/LLVMIR/Import/import-failure.ll
+++ b/mlir/test/Target/LLVMIR/Import/import-failure.ll
@@ -65,7 +65,7 @@ define void @access_group(ptr %arg1) {
 ; CHECK:      <unknown>
 ; CHECK-SAME: warning: expected all loop properties to be either debug locations or metadata nodes
 ; CHECK:      <unknown>
-; CHECK-SAME: warning: unhandled metadata: !0 = distinct !{!0, i32 42}
+; CHECK-SAME: warning: unhandled metadata: ![[LOOP_ID:[0-9]+]] = distinct !{![[LOOP_ID]], i32 42}
 define void @invalid_loop_node(i64 %n, ptr %A) {
 entry:
   br label %end, !llvm.loop !0
@@ -80,7 +80,7 @@ end:
 ; CHECK:      <unknown>
 ; CHECK-SAME: warning: cannot import empty loop property
 ; CHECK:      <unknown>
-; CHECK-SAME: warning: unhandled metadata: !0 = distinct !{!0, !1}
+; CHECK-SAME: warning: unhandled metadata: ![[EMPTY_LOOP:[0-9]+]] = distinct !{![[EMPTY_LOOP]], ![[EMPTY_PROP:[0-9]+]]}
 define void @invalid_loop_node(i64 %n, ptr %A) {
 entry:
   br label %end, !llvm.loop !0
@@ -96,7 +96,7 @@ end:
 ; CHECK:      <unknown>
 ; CHECK-SAME: warning: cannot import loop property without a name
 ; CHECK:      <unknown>
-; CHECK-SAME: warning: unhandled metadata: !0 = distinct !{!0, !1}
+; CHECK-SAME: warning: unhandled metadata: ![[UNNAMED_LOOP:[0-9]+]] = distinct !{![[UNNAMED_LOOP]], ![[UNNAMED_PROP:[0-9]+]]}
 define void @invalid_loop_node(i64 %n, ptr %A) {
 entry:
   br label %end, !llvm.loop !0
@@ -112,7 +112,7 @@ end:
 ; CHECK:      <unknown>
 ; CHECK-SAME: warning: cannot import loop properties with duplicated names llvm.loop.disable_nonforced
 ; CHECK:      <unknown>
-; CHECK-SAME: warning: unhandled metadata: !0 = distinct !{!0, !1, !1}
+; CHECK-SAME: warning: unhandled metadata: ![[DUP_LOOP:[0-9]+]] = distinct !{![[DUP_LOOP]], ![[DUP_PROP:[0-9]+]], ![[DUP_PROP]]}
 define void @unsupported_loop_annotation(i64 %n, ptr %A) {
 entry:
   br label %end, !llvm.loop !0
@@ -128,7 +128,7 @@ end:
 ; CHECK:      <unknown>
 ; CHECK-SAME: warning: expected metadata node llvm.loop.disable_nonforced to hold no value
 ; CHECK:      <unknown>
-; CHECK-SAME: warning: unhandled metadata: !0 = distinct !{!0, !1}
+; CHECK-SAME: warning: unhandled metadata: ![[VALUE_LOOP:[0-9]+]] = distinct !{![[VALUE_LOOP]], ![[VALUE_PROP:[0-9]+]]}
 define void @unsupported_loop_annotation(i64 %n, ptr %A) {
 entry:
   br label %end, !llvm.loop !0
@@ -144,7 +144,7 @@ end:
 ; CHECK:      <unknown>
 ; CHECK-SAME: warning: expected metadata nodes llvm.loop.unroll.enable and llvm.loop.unroll.disable to be mutually exclusive
 ; CHECK:      <unknown>
-; CHECK-SAME: warning: unhandled metadata: !0 = distinct !{!0, !1, !2}
+; CHECK-SAME: warning: unhandled metadata: ![[EXCLUSIVE_LOOP:[0-9]+]] = distinct !{![[EXCLUSIVE_LOOP]], ![[ENABLE_PROP:[0-9]+]], ![[DISABLE_PROP:[0-9]+]]}
 define void @unsupported_loop_annotation(i64 %n, ptr %A) {
 entry:
   br label %end, !llvm.loop !0
@@ -161,7 +161,7 @@ end:
 ; CHECK:      <unknown>
 ; CHECK-SAME: warning: expected metadata node llvm.loop.vectorize.width to hold an i32 value
 ; CHECK:      <unknown>
-; CHECK-SAME: warning: unhandled metadata: !0 = distinct !{!0, !1}
+; CHECK-SAME: warning: unhandled metadata: ![[WIDTH_LOOP:[0-9]+]] = distinct !{![[WIDTH_LOOP]], ![[WIDTH_PROP:[0-9]+]]}
 define void @unsupported_loop_annotation(i64 %n, ptr %A) {
 entry:
   br label %end, !llvm.loop !0
@@ -177,7 +177,7 @@ end:
 ; CHECK:      <unknown>
 ; CHECK-SAME: warning: expected metadata node llvm.loop.vectorize.followup_all to hold an MDNode
 ; CHECK:      <unknown>
-; CHECK-SAME: warning: unhandled metadata: !0 = distinct !{!0, !1}
+; CHECK-SAME: warning: unhandled metadata: ![[FOLLOWUP_LOOP:[0-9]+]] = distinct !{![[FOLLOWUP_LOOP]], ![[FOLLOWUP_PROP:[0-9]+]]}
 define void @unsupported_loop_annotation(i64 %n, ptr %A) {
 entry:
   br label %end, !llvm.loop !0
@@ -193,7 +193,7 @@ end:
 ; CHECK:      <unknown>
 ; CHECK-SAME: warning: expected metadata node llvm.loop.parallel_accesses to hold one or multiple MDNodes
 ; CHECK:      <unknown>
-; CHECK-SAME: warning: unhandled metadata: !0 = distinct !{!0, !1}
+; CHECK-SAME: warning: unhandled metadata: ![[PARALLEL_LOOP:[0-9]+]] = distinct !{![[PARALLEL_LOOP]], ![[PARALLEL_PROP:[0-9]+]]}
 define void @unsupported_loop_annotation(i64 %n, ptr %A) {
 entry:
   br label %end, !llvm.loop !0
@@ -209,7 +209,7 @@ end:
 ; CHECK:      <unknown>
 ; CHECK-SAME: warning: unknown loop annotation llvm.loop.typo
 ; CHECK:      <unknown>
-; CHECK-SAME: warning: unhandled metadata: !0 = distinct !{!0, !1, !2}
+; CHECK-SAME: warning: unhandled metadata: ![[UNKNOWN_LOOP:[0-9]+]] = distinct !{![[UNKNOWN_LOOP]], ![[KNOWN_PROP:[0-9]+]], ![[UNKNOWN_PROP:[0-9]+]]}
 define void @unsupported_loop_annotation(i64 %n, ptr %A) {
 entry:
   br label %end, !llvm.loop !0
@@ -241,7 +241,7 @@ end:
 ; // -----
 
 ; CHECK:      <unknown>
-; CHECK-SAME: warning: dropped instruction: call void @llvm.experimental.noalias.scope.decl(metadata !0)
+; CHECK-SAME: warning: dropped instruction: call void @llvm.experimental.noalias.scope.decl(metadata ![[SCOPE_LIST:[0-9]+]])
 define void @unused_scope() {
   call void @llvm.experimental.noalias.scope.decl(metadata !0)
   ret void
@@ -320,7 +320,7 @@ bb1:
 !10 = !{ i32 1, !"foo", i32 1 }
 !11 = !{ i32 4, !"bar", i32 37 }
 !12 = !{ i32 2, !"qux", i32 42 }
-; CHECK: unsupported module flag value for key 'qux' : !4 = !{!"foo", i32 1}
+; CHECK: unsupported module flag value for key 'qux' : ![[FLAG_VALUE:[0-9]+]] = !{!"foo", i32 1}
 !13 = !{ i32 3, !"qux", !{ !"foo", i32 1 }}
 !llvm.module.flags = !{ !10, !11, !12, !13 }
 
diff --git a/polly/test/ForwardOpTree/atax.ll b/polly/test/ForwardOpTree/atax.ll
index 3dfe3fa0aa8e6..3d3a44b763aa3 100644
--- a/polly/test/ForwardOpTree/atax.ll
+++ b/polly/test/ForwardOpTree/atax.ll
@@ -87,7 +87,7 @@ declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i32, i1)
 ; CHECK-NEXT:             MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 1]
 ; CHECK-NEXT:                 { Stmt_for_body3[i0] -> MemRef1__phi[] };
 ; CHECK-NEXT:             Instructions {
-; CHECK-NEXT:                   store double 0.000000e+00, ptr %arrayidx5, align 8, !tbaa !2
+; CHECK-NEXT:                   store double 0.000000e+00, ptr %arrayidx5, align 8, !tbaa !13
 ; CHECK-NEXT:             }
 ; CHECK-NEXT:     Stmt_for_body8
 ; CHECK-NEXT:             MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 1]
@@ -105,11 +105,11 @@ declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i32, i1)
 ; CHECK-NEXT:                 { Stmt_for_body8[i0, i1] -> MemRef_add[] };
 ; CHECK-NEXT:             Instructions {
 ; CHECK-NEXT:                   %0 = phi double [ 0.000000e+00, %for.body3 ], [ %add, %for.body8 ]
-; CHECK-NEXT:                   %1 = load double, ptr %arrayidx14, align 8, !tbaa !2
-; CHECK-NEXT:                   %2 = load double, ptr %arrayidx16, align 8, !tbaa !2
+; CHECK-NEXT:                   %1 = load double, ptr %arrayidx14, align 8, !tbaa !13
+; CHECK-NEXT:                   %2 = load double, ptr %arrayidx16, align 8, !tbaa !13
 ; CHECK-NEXT:                   %mul = fmul double %1, %2
 ; CHECK-NEXT:                   %add = fadd double %0, %mul
-; CHECK-NEXT:                   store double %add, ptr %arrayidx5, align 8, !tbaa !2
+; CHECK-NEXT:                   store double %add, ptr %arrayidx5, align 8, !tbaa !13
 ; CHECK-NEXT:                   %exitcond = icmp eq i64 %indvars.iv.next, 2
 ; CHECK-NEXT:             }
 ; CHECK-NEXT:     Stmt_for_end21
@@ -131,11 +131,11 @@ declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i32, i1)
 ; CHECK-NEXT:                 { Stmt_for_body24[i0, i1] -> MemRef_y[i1] };
 ; CHECK-NEXT:             Instructions {
 ; CHECK-NEXT:                   %3 = phi double [ %add, %for.end21 ], [ %.pre, %for.body24.for.body24_crit_edge ]
-; CHECK-NEXT:                   %4 = load double, ptr %arrayidx26, align 8, !tbaa !2
-; CHECK-NEXT:                   %5 = load double, ptr %arrayidx30, align 8, !tbaa !2
+; CHECK-NEXT:                   %4 = load double, ptr %arrayidx26, align 8, !tbaa !13
+; CHECK-NEXT:                   %5 = load double, ptr %arrayidx30, align 8, !tbaa !13
 ; CHECK-NEXT:                   %mul33 = fmul double %5, %3
 ; CHECK-NEXT:                   %add34 = fadd double %4, %mul33
-; CHECK-NEXT:                   store double %add34, ptr %arrayidx26, align 8, !tbaa !2
+; CHECK-NEXT:                   store double %add34, ptr %arrayidx26, align 8, !tbaa !13
 ; CHECK-NEXT:                   %exitcond7 = icmp eq i64 %indvars.iv.next6, 2
 ; CHECK-NEXT:             }
 ; CHECK-NEXT:     Stmt_for_body24_for_body24_crit_edge
@@ -144,6 +144,6 @@ declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i32, i1)
 ; CHECK-NEXT:             ReadAccess :=       [Reduction Type: NONE] [Scalar: 0]
 ; CHECK-NEXT:                 { Stmt_for_body24_for_body24_crit_edge[i0, i1] -> MemRef_tmp[i0] };
 ; CHECK-NEXT:             Instructions {
-; CHECK-NEXT:                   %.pre = load double, ptr %arrayidx5, align 8, !tbaa !2
+; CHECK-NEXT:                   %.pre = load double, ptr %arrayidx5, align 8, !tbaa !13
 ; CHECK-NEXT:             }
 ; CHECK-NEXT: }
diff --git a/polly/test/ForwardOpTree/jacobi-1d.ll b/polly/test/ForwardOpTree/jacobi-1d.ll
index 3bc504d88c0eb..fbae4c7bc227b 100644
--- a/polly/test/ForwardOpTree/jacobi-1d.ll
+++ b/polly/test/ForwardOpTree/jacobi-1d.ll
@@ -74,8 +74,8 @@ for.end35:                                        ; preds = %for.inc33
 ; CHECK-NEXT:             MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 1]
 ; CHECK-NEXT:                 { Stmt_for_body[i0] -> MemRef2__phi[] };
 ; CHECK-NEXT:             Instructions {
-; CHECK-NEXT:                   %.pre = load double, ptr %A, align 8, !tbaa !2
-; CHECK-NEXT:                   %.pre10 = load double, ptr %arrayidx6.phi.trans.insert, align 8, !tbaa !2
+; CHECK-NEXT:                   %.pre = load double, ptr %A, align 8, !tbaa !13
+; CHECK-NEXT:                   %.pre10 = load double, ptr %arrayidx6.phi.trans.insert, align 8, !tbaa !13
 ; CHECK-NEXT:             }
 ; CHECK-NEXT:     Stmt_for_body3
 ; CHECK-NEXT:             MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 1]
@@ -96,10 +96,10 @@ for.end35:                                        ; preds = %for.inc33
 ; CHECK-NEXT:                   %0 = phi double [ %.pre10, %for.body ], [ %2, %for.body3 ]
 ; CHECK-NEXT:                   %1 = phi double [ %.pre, %for.body ], [ %0, %for.body3 ]
 ; CHECK-NEXT:                   %add = fadd double %1, %0
-; CHECK-NEXT:                   %2 = load double, ptr %arrayidx9, align 8, !tbaa !2
+; CHECK-NEXT:                   %2 = load double, ptr %arrayidx9, align 8, !tbaa !13
 ; CHECK-NEXT:                   %add10 = fadd double %add, %2
 ; CHECK-NEXT:                   %mul = fmul double %add10, 3.333300e-01
-; CHECK-NEXT:                   store double %mul, ptr %arrayidx12, align 8, !tbaa !2
+; CHECK-NEXT:                   store double %mul, ptr %arrayidx12, align 8, !tbaa !13
 ; CHECK-NEXT:                   %exitcond = icmp eq i64 %indvars.iv.next, 3
 ; CHECK-NEXT:             }
 ; CHECK-NEXT: }
diff --git a/polly/test/ScopInfo/preserve-equiv-class-order-in-basic_block.ll b/polly/test/ScopInfo/preserve-equiv-class-order-in-basic_block.ll
index 800b0339a1422..adcd95a277e62 100644
--- a/polly/test/ScopInfo/preserve-equiv-class-order-in-basic_block.ll
+++ b/polly/test/ScopInfo/preserve-equiv-class-order-in-basic_block.ll
@@ -77,7 +77,7 @@ for.end13:                                        ; preds = %for.inc11
 ; CHECK-NEXT:            MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 1]
 ; CHECK-NEXT:                { Stmt_for_end_a[] -> MemRef_conv[] };
 ; CHECK-NEXT:            Instructions {
-; CHECK-NEXT:                  %1 = load i32, ptr @e, align 4, !tbaa !0
+; CHECK-NEXT:                  %1 = load i32, ptr @e, align 4, !tbaa !4
 ; CHECK-NEXT:                  %2 = trunc i32 %1 to i16
 ; CHECK-NEXT:                  %conv = and i16 %2, 1
 ; CHECK-NEXT:                  %tobool = icmp eq i16 %conv, 0
@@ -90,5 +90,5 @@ for.end13:                                        ; preds = %for.inc11
 ; CHECK-NEXT:            MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 0]
 ; CHECK-NEXT:                { Stmt_for_end[] -> MemRef_e[0] };
 ; CHECK-NEXT:            Instructions {
-; CHECK-NEXT:                  store i32 2, ptr @e, align 4, !tbaa !0
+; CHECK-NEXT:                  store i32 2, ptr @e, align 4, !tbaa !4
 ; CHECK-NEXT:            }
diff --git a/polly/test/ScopInfo/stmt_split_exit_of_region_stmt.ll b/polly/test/ScopInfo/stmt_split_exit_of_region_stmt.ll
index 54832607f11d5..8a160c299172b 100644
--- a/polly/test/ScopInfo/stmt_split_exit_of_region_stmt.ll
+++ b/polly/test/ScopInfo/stmt_split_exit_of_region_stmt.ll
@@ -19,7 +19,7 @@
 ; CHECK-NEXT:       MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 0]
 ; CHECK-NEXT:           { Stmt_Stmt[i0] -> MemRef_A[i0] };
 ; CHECK-NEXT:       Instructions {
-; CHECK-NEXT:             store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !0
+; CHECK-NEXT:             store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !1
 ; CHECK-NEXT:       }
 ; CHECK-NEXT:   Stmt_Stmt_b
 ; CHECK-NEXT:       Domain :=
diff --git a/polly/test/ScopInfo/stmt_split_no_after_split.ll b/polly/test/ScopInfo/stmt_split_no_after_split.ll
index 0a4284bdd34f5..b0dffa98c7e79 100644
--- a/polly/test/ScopInfo/stmt_split_no_after_split.ll
+++ b/polly/test/ScopInfo/stmt_split_no_after_split.ll
@@ -9,7 +9,7 @@
 ; CHECK-NEXT:       MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 0]
 ; CHECK-NEXT:           { Stmt_Stmt[i0] -> MemRef_A[i0] };
 ; CHECK-NEXT:       Instructions {
-; CHECK-NEXT:             store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !0
+; CHECK-NEXT:             store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !1
 ; CHECK-NEXT:       }
 ; CHECK-NEXT:   }
 ;
diff --git a/polly/test/ScopInfo/stmt_split_no_dependence.ll b/polly/test/ScopInfo/stmt_split_no_dependence.ll
index ed2180407c68d..d129e58c11204 100644
--- a/polly/test/ScopInfo/stmt_split_no_dependence.ll
+++ b/polly/test/ScopInfo/stmt_split_no_dependence.ll
@@ -17,7 +17,7 @@
 ; CHECK-NEXT:       MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 0]
 ; CHECK-NEXT:           { Stmt_Stmt[i0] -> MemRef_A[i0] };
 ; CHECK-NEXT:       Instructions {
-; CHECK-NEXT:             store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !0
+; CHECK-NEXT:             store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !1
 ; CHECK-NEXT:       }
 ; CHECK-NEXT:  	Stmt_Stmt_b
 ; CHECK-NEXT:       Domain :=
diff --git a/polly/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll b/polly/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll
index 0521525e272b3..1150c5ead3065 100644
--- a/polly/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll
+++ b/polly/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll
@@ -9,7 +9,7 @@
 ; CHECK-NEXT:       MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 0]
 ; CHECK-NEXT:           { Stmt_Stmt[i0] -> MemRef_A[i0] };
 ; CHECK-NEXT:       Instructions {
-; CHECK-NEXT:             store i32 %phi, ptr %arrayidx, align 4, !polly_split_after !0
+; CHECK-NEXT:             store i32 %phi, ptr %arrayidx, align 4, !polly_split_after !1
 ; CHECK-NEXT:       }
 ; CHECK-NEXT: 	Stmt_Stmt_b
 ; CHECK-NEXT:       Domain :=
diff --git a/polly/test/ScopInfo/stmt_split_phi_in_stmt.ll b/polly/test/ScopInfo/stmt_split_phi_in_stmt.ll
index 82a85aa5f0099..2ba38dc7b3a4b 100644
--- a/polly/test/ScopInfo/stmt_split_phi_in_stmt.ll
+++ b/polly/test/ScopInfo/stmt_split_phi_in_stmt.ll
@@ -9,7 +9,7 @@
 ; CHECK-NEXT:       MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 0]
 ; CHECK-NEXT:           { Stmt_Stmt[i0] -> MemRef_A[i0] };
 ; CHECK-NEXT:       Instructions {
-; CHECK-NEXT:             store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !0
+; CHECK-NEXT:             store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !1
 ; CHECK-NEXT:       }
 ; CHECK-NEXT:  	Stmt_Stmt_b
 ; CHECK-NEXT:       Domain :=
diff --git a/polly/test/ScopInfo/stmt_split_scalar_dependence.ll b/polly/test/ScopInfo/stmt_split_scalar_dependence.ll
index 1f21c0ce7225f..a98a0538fb3a5 100644
--- a/polly/test/ScopInfo/stmt_split_scalar_dependence.ll
+++ b/polly/test/ScopInfo/stmt_split_scalar_dependence.ll
@@ -12,7 +12,7 @@
 ; CHECK-NEXT:           { Stmt_Stmt[i0] -> MemRef_a[] };
 ; CHECK-NEXT:       Instructions {
 ; CHECK-NEXT:             %a = fadd double 2.100000e+01, 2.100000e+01
-; CHECK-NEXT:             store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !0
+; CHECK-NEXT:             store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !1
 ; CHECK-NEXT:       }
 ; CHECK-NEXT:   Stmt_Stmt_b
 ; CHECK-NEXT:       Domain :=
diff --git a/polly/test/ScopInfo/stmt_split_within_loop.ll b/polly/test/ScopInfo/stmt_split_within_loop.ll
index 580ffab567846..6164cce2de7fd 100644
--- a/polly/test/ScopInfo/stmt_split_within_loop.ll
+++ b/polly/test/ScopInfo/stmt_split_within_loop.ll
@@ -9,7 +9,7 @@
 ; CHECK-NEXT:       MustWriteAccess :=	[Reduction Type: NONE] [Scalar: 0]
 ; CHECK-NEXT:           { Stmt_Stmt[i0, i1] -> MemRef_A[i0] };
 ; CHECK-NEXT:       Instructions {
-; CHECK-NEXT:             store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !0
+; CHECK-NEXT:             store i32 %i.0, ptr %arrayidx, align 4, !polly_split_after !1
 ; CHECK-NEXT:       }
 ; CHECK-NEXT:  	Stmt_Stmt_b
 ; CHECK-NEXT:       Domain :=



More information about the flang-commits mailing list