[clang] [compiler-rt] [flang] [llvm] [mlir] [DebugMetadata][DwarfDebug][CodeView] Support function-local static variables in lexical block scopes (6/7) (PR #187927)

Vladislav Dzhidzhoev via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 31 07:01:20 PDT 2026


https://github.com/dzhidzhoev updated https://github.com/llvm/llvm-project/pull/187927

>From c06a34bd49cf8185c5803e44cc20245486762c17 Mon Sep 17 00:00:00 2001
From: Kristina Bessonova <kbessonova at accesssoftek.com>
Date: Mon, 13 Mar 2023 13:38:42 +0100
Subject: [PATCH 1/3] [DebugMetadata][DwarfDebug][CodeView] Support
 function-local static variables in lexical block scopes (6/7)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

RFC https://discourse.llvm.org/t/rfc-dwarfdebug-fix-and-improve-handling-imported-entities-types-and-static-local-in-subprogram-and-lexical-block-scopes/68544

Similar to imported declarations and types, the patch tracks function-local
static variables (globals in terms of LLVM IR) in DISubprogram's 'retainedNodes'.
DwarfDebug is adjusted in accordance with the aforementioned metadata change and
provided a support of static locals scoped by a lexical block.
CodeViewDebug is modified to collect global variables from DISubprogram's
'retainedNodes' too.

The patch assumes that DICompileUnit's 'globals' no longer tracks static locals
and DwarfDebug would assert if any locally-scoped variables get placed there.

This change has already been reviewed in https://reviews.llvm.org/D144008, but I’m opening a new PR because it has been a while since it was approved.

Authored-by: Kristina Bessonova <kbessonova at accesssoftek.com>
---
 clang/test/OpenMP/error_codegen.cpp           |  91 +++++------
 .../lib/Optimizer/Transforms/AddDebugInfo.cpp |   8 +-
 llvm/include/llvm/IR/DIBuilder.h              |   6 +-
 llvm/include/llvm/IR/DebugInfo.h              |   1 +
 llvm/include/llvm/IR/DebugInfoMetadata.h      |  75 +++++++--
 llvm/include/llvm/IR/Metadata.h               |  22 +++
 llvm/lib/Bitcode/Reader/MetadataLoader.cpp    | 115 ++++++--------
 llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 102 ++++++------
 llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h   |   4 +
 llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp    |  42 +++--
 llvm/lib/IR/DIBuilder.cpp                     |  11 +-
 llvm/lib/IR/DebugInfo.cpp                     |  21 ++-
 llvm/lib/IR/DebugInfoMetadata.cpp             |  30 +---
 llvm/lib/IR/Verifier.cpp                      |  14 +-
 .../Target/BPF/BPFAbstractMemberAccess.cpp    |   2 +-
 llvm/lib/Target/BPF/BTFDebug.cpp              |   4 +-
 llvm/lib/Transforms/Coroutines/CoroFrame.cpp  |   6 +-
 .../Instrumentation/InstrProfiling.cpp        |   1 +
 llvm/lib/Transforms/Utils/CloneFunction.cpp   |  15 ++
 llvm/lib/Transforms/Utils/Debugify.cpp        |   4 +-
 .../DIModule-fortran-external-module.ll       |   5 +-
 llvm/test/Bitcode/upgrade-cu-static-locals.ll | 108 +++++++++++++
 .../Bitcode/upgrade-cu-static-locals.ll.bc    | Bin 0 -> 2732 bytes
 .../arm64-2011-03-17-AsmPrinterCrash.ll       |   4 +-
 .../CodeGen/BPF/BTF/static-var-inited-sec.ll  |   5 +-
 .../test/CodeGen/BPF/BTF/static-var-inited.ll |   5 +-
 .../BPF/BTF/static-var-readonly-sec.ll        |   5 +-
 .../CodeGen/BPF/BTF/static-var-readonly.ll    |   5 +-
 llvm/test/CodeGen/BPF/BTF/static-var-sec.ll   |   5 +-
 llvm/test/CodeGen/BPF/BTF/static-var.ll       |   5 +-
 llvm/test/CodeGen/BPF/dwarfdump.ll            |   5 +-
 llvm/test/CodeGen/PowerPC/pr24546.ll          |   5 +-
 .../test/CodeGen/X86/dbg-distringtype-uint.ll |   5 +-
 llvm/test/DebugInfo/COFF/fortran-basic.ll     |   4 +-
 .../DebugInfo/COFF/fortran-contained-proc.ll  |   4 +-
 llvm/test/DebugInfo/COFF/global_visibility.ll |   8 +-
 llvm/test/DebugInfo/COFF/type-quals.ll        |   4 +-
 .../Generic/2009-11-05-DeadGlobalVariable.ll  |   4 +-
 .../DebugInfo/Generic/inlined-static-var.ll   |   9 +-
 .../Generic/verifier-invalid-dicompileunit.ll |  62 ++++++++
 .../Generic/verifier-invalid-disubprogram.ll  |   2 +-
 .../Symbolize/XCOFF/xcoff-symbolize-data.ll   |   5 +-
 .../test/DebugInfo/X86/DW_AT_specification.ll |   4 +-
 .../DebugInfo/X86/dbg-value-transfer-order.ll |   4 +-
 .../X86/dimodule-external-fortran.ll          |   5 +-
 llvm/test/DebugInfo/X86/distringtype.ll       |   4 +-
 .../X86/global-sra-struct-fit-segment.ll      |   4 +-
 .../global-sra-struct-part-overlap-segment.ll |   5 +-
 llvm/test/DebugInfo/X86/gnu-public-names.ll   |   5 +-
 .../DebugInfo/X86/lexical-block-static-var.ll | 145 ++++++++++++++++++
 llvm/test/DebugInfo/X86/namelist1.ll          |   4 +-
 .../DebugInfo/X86/sdag-dbgvalue-phi-use-4.ll  | 107 +++++++------
 llvm/test/DebugInfo/duplicate_dbgvalue.ll     |   5 +-
 .../InstrProfiling/debug-info-correlate.ll    |   3 +-
 .../Transforms/Util/clone-dicompileunit.ll    |  11 +-
 .../DWARF/Inputs/ThreadLocalStorage.ll        |   4 +-
 .../Transforms/Utils/CloningTest.cpp          |  40 +++--
 .../mlir/Dialect/LLVMIR/LLVMAttrDefs.td       |   4 +-
 .../Dialect/LLVMIR/LLVMDialectBytecode.td     |   2 +-
 mlir/lib/CAPI/Dialect/LLVM.cpp                |   2 +-
 mlir/lib/Target/LLVMIR/DebugImporter.cpp      |   9 +-
 mlir/lib/Target/LLVMIR/DebugTranslation.cpp   |  20 ++-
 mlir/lib/Target/LLVMIR/DebugTranslation.h     |   4 +
 mlir/lib/Target/LLVMIR/ModuleTranslation.cpp  |  29 +++-
 mlir/test/Target/LLVMIR/llvmir-debug.mlir     |   6 +-
 65 files changed, 856 insertions(+), 408 deletions(-)
 create mode 100644 llvm/test/Bitcode/upgrade-cu-static-locals.ll
 create mode 100644 llvm/test/Bitcode/upgrade-cu-static-locals.ll.bc
 create mode 100644 llvm/test/DebugInfo/Generic/verifier-invalid-dicompileunit.ll
 create mode 100644 llvm/test/DebugInfo/X86/lexical-block-static-var.ll

diff --git a/clang/test/OpenMP/error_codegen.cpp b/clang/test/OpenMP/error_codegen.cpp
index 0efb0ab098cf3..def68ea020c63 100644
--- a/clang/test/OpenMP/error_codegen.cpp
+++ b/clang/test/OpenMP/error_codegen.cpp
@@ -565,7 +565,7 @@ int main (int argc, char **argv) {
 //
 //
 // SIMD-LABEL: define linkonce_odr noundef i32 @_Z5tmainIiLi10EEiT_PPc(
-// SIMD-SAME: i32 noundef [[ARGC:%.*]], ptr noundef [[ARGV:%.*]]) #[[ATTR0]] comdat !dbg [[DBG21:![0-9]+]] {
+// SIMD-SAME: i32 noundef [[ARGC:%.*]], ptr noundef [[ARGV:%.*]]) #[[ATTR0]] comdat !dbg [[DBG22:![0-9]+]] {
 // SIMD-NEXT:  [[ENTRY:.*:]]
 // SIMD-NEXT:    [[ARGC_ADDR:%.*]] = alloca i32, align 4
 // SIMD-NEXT:    [[ARGV_ADDR:%.*]] = alloca ptr, align 8
@@ -630,7 +630,7 @@ int main (int argc, char **argv) {
 //.
 // SIMD: [[META0:![0-9]+]] = !DIGlobalVariableExpression(var: [[META1:![0-9]+]], expr: !DIExpression())
 // SIMD: [[META1]] = distinct !DIGlobalVariable(name: "a", scope: [[DBG2]], file: [[META3:![0-9]+]], line: 61, type: [[META6:![0-9]+]], isLocal: true, isDefinition: true)
-// SIMD: [[DBG2]] = distinct !DISubprogram(name: "main", scope: [[META3]], file: [[META3]], line: 59, type: [[META4:![0-9]+]], scopeLine: 59, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META10:![0-9]+]], retainedNodes: [[META22:![0-9]+]])
+// SIMD: [[DBG2]] = distinct !DISubprogram(name: "main", scope: [[META3]], file: [[META3]], line: 59, type: [[META4:![0-9]+]], scopeLine: 59, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META10:![0-9]+]], retainedNodes: [[META19:![0-9]+]])
 // SIMD: [[META3]] = !DIFile(filename: "{{.*}}error_codegen.cpp", directory: {{.*}})
 // SIMD: [[META4]] = !DISubroutineType(types: [[META5:![0-9]+]])
 // SIMD: [[META5]] = !{[[META6]], [[META6]], [[META7:![0-9]+]]}
@@ -640,20 +640,21 @@ int main (int argc, char **argv) {
 // SIMD: [[META9]] = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
 // SIMD: [[META10]] = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_11, file: [[META11:![0-9]+]], producer: "{{.*}}clang version {{.*}}", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: [[META12:![0-9]+]], splitDebugInlining: false, nameTableKind: None)
 // SIMD: [[META11]] = !DIFile(filename: "{{.*}}<stdin>", directory: {{.*}})
-// SIMD: [[META12]] = !{[[META0]], [[META13:![0-9]+]], [[META19:![0-9]+]]}
+// SIMD: [[META12]] = !{[[META13:![0-9]+]]}
 // SIMD: [[META13]] = !DIGlobalVariableExpression(var: [[META14:![0-9]+]], expr: !DIExpression())
 // SIMD: [[META14]] = distinct !DIGlobalVariable(scope: null, file: [[META3]], line: 63, type: [[META15:![0-9]+]], isLocal: true, isDefinition: true)
 // SIMD: [[META15]] = !DICompositeType(tag: DW_TAG_array_type, baseType: [[META16:![0-9]+]], size: 32, elements: [[META17:![0-9]+]])
 // SIMD: [[META16]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: [[META9]])
 // SIMD: [[META17]] = !{[[META18:![0-9]+]]}
 // SIMD: [[META18]] = !DISubrange(count: 4)
-// SIMD: [[META19]] = !DIGlobalVariableExpression(var: [[META20:![0-9]+]], expr: !DIExpression())
-// SIMD: [[META20]] = distinct !DIGlobalVariable(name: "a", scope: [[DBG21]], file: [[META3]], line: 22, type: [[META6]], isLocal: false, isDefinition: true)
-// SIMD: [[DBG21]] = distinct !DISubprogram(name: "tmain<int, 10>", linkageName: "_Z5tmainIiLi10EEiT_PPc", scope: [[META3]], file: [[META3]], line: 20, type: [[META4]], scopeLine: 20, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META10]], templateParams: [[META23:![0-9]+]], retainedNodes: [[META22]])
-// SIMD: [[META22]] = !{}
-// SIMD: [[META23]] = !{[[META24:![0-9]+]], [[META25:![0-9]+]]}
-// SIMD: [[META24]] = !DITemplateTypeParameter(name: "T", type: [[META6]])
-// SIMD: [[META25]] = !DITemplateValueParameter(name: "N", type: [[META6]], value: i32 10)
+// SIMD: [[META19]] = !{[[META0]]}
+// SIMD: [[META20:![0-9]+]] = !DIGlobalVariableExpression(var: [[META21:![0-9]+]], expr: !DIExpression())
+// SIMD: [[META21]] = distinct !DIGlobalVariable(name: "a", scope: [[DBG22]], file: [[META3]], line: 22, type: [[META6]], isLocal: false, isDefinition: true)
+// SIMD: [[DBG22]] = distinct !DISubprogram(name: "tmain<int, 10>", linkageName: "_Z5tmainIiLi10EEiT_PPc", scope: [[META3]], file: [[META3]], line: 20, type: [[META4]], scopeLine: 20, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META10]], templateParams: [[META24:![0-9]+]], retainedNodes: [[META23:![0-9]+]])
+// SIMD: [[META23]] = !{[[META20]]}
+// SIMD: [[META24]] = !{[[META25:![0-9]+]], [[META26:![0-9]+]]}
+// SIMD: [[META25]] = !DITemplateTypeParameter(name: "T", type: [[META6]])
+// SIMD: [[META26]] = !DITemplateValueParameter(name: "N", type: [[META6]], value: i32 10)
 // SIMD: [[DBG29]] = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: [[META3]], file: [[META3]], line: 17, type: [[META30:![0-9]+]], scopeLine: 17, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META10]])
 // SIMD: [[META30]] = !DISubroutineType(types: [[META31:![0-9]+]])
 // SIMD: [[META31]] = !{null}
@@ -696,40 +697,40 @@ int main (int argc, char **argv) {
 // SIMD: [[DBG68]] = !DILocation(line: 81, column: 24, scope: [[DBG2]])
 // SIMD: [[DBG69]] = !DILocation(line: 81, column: 3, scope: [[DBG2]])
 // SIMD: [[DBG70]] = !DILocation(line: 82, column: 1, scope: [[DBG2]])
-// SIMD: [[META71]] = !DILocalVariable(name: "argc", arg: 1, scope: [[DBG21]], file: [[META3]], line: 20, type: [[META6]])
-// SIMD: [[META72]] = !DILocation(line: 20, column: 13, scope: [[DBG21]])
-// SIMD: [[META73]] = !DILocalVariable(name: "argv", arg: 2, scope: [[DBG21]], file: [[META3]], line: 20, type: [[META7]])
-// SIMD: [[META74]] = !DILocation(line: 20, column: 26, scope: [[DBG21]])
-// SIMD: [[META75]] = !DILocalVariable(name: "b", scope: [[DBG21]], file: [[META3]], line: 21, type: [[META6]])
-// SIMD: [[META76]] = !DILocation(line: 21, column: 5, scope: [[DBG21]])
-// SIMD: [[DBG77]] = !DILocation(line: 21, column: 9, scope: [[DBG21]])
-// SIMD: [[META78]] = !DILocalVariable(name: "c", scope: [[DBG21]], file: [[META3]], line: 21, type: [[META6]])
-// SIMD: [[META79]] = !DILocation(line: 21, column: 15, scope: [[DBG21]])
-// SIMD: [[META80]] = !DILocalVariable(name: "d", scope: [[DBG21]], file: [[META3]], line: 21, type: [[META6]])
-// SIMD: [[META81]] = !DILocation(line: 21, column: 18, scope: [[DBG21]])
-// SIMD: [[META82]] = !DILocalVariable(name: "e", scope: [[DBG21]], file: [[META3]], line: 21, type: [[META6]])
-// SIMD: [[META83]] = !DILocation(line: 21, column: 21, scope: [[DBG21]])
-// SIMD: [[META84]] = !DILocalVariable(name: "f", scope: [[DBG21]], file: [[META3]], line: 21, type: [[META6]])
-// SIMD: [[META85]] = !DILocation(line: 21, column: 24, scope: [[DBG21]])
-// SIMD: [[META86]] = !DILocalVariable(name: "g", scope: [[DBG21]], file: [[META3]], line: 21, type: [[META6]])
-// SIMD: [[META87]] = !DILocation(line: 21, column: 27, scope: [[DBG21]])
-// SIMD: [[META88]] = !DILocalVariable(name: "str1", scope: [[DBG21]], file: [[META3]], line: 23, type: [[META15]])
-// SIMD: [[META89]] = !DILocation(line: 23, column: 14, scope: [[DBG21]])
-// SIMD: [[META90]] = !DILocalVariable(name: "str2", scope: [[DBG21]], file: [[META3]], line: 24, type: [[META53]])
-// SIMD: [[META91]] = !DILocation(line: 24, column: 15, scope: [[DBG21]])
-// SIMD: [[META92]] = !DILocalVariable(name: "str3", scope: [[DBG21]], file: [[META3]], line: 25, type: [[META56]])
-// SIMD: [[META93]] = !DILocation(line: 25, column: 8, scope: [[DBG21]])
-// SIMD: [[META94]] = !DILocalVariable(name: "str4", scope: [[DBG21]], file: [[META3]], line: 26, type: [[META8]])
-// SIMD: [[META95]] = !DILocation(line: 26, column: 9, scope: [[DBG21]])
-// SIMD: [[DBG96]] = !DILocation(line: 26, column: 16, scope: [[DBG21]])
-// SIMD: [[META97]] = !DILocalVariable(name: "str5", scope: [[DBG21]], file: [[META3]], line: 27, type: [[META62]])
-// SIMD: [[META98]] = !DILocation(line: 27, column: 16, scope: [[DBG21]])
-// SIMD: [[DBG99]] = !DILocation(line: 27, column: 23, scope: [[DBG21]])
-// SIMD: [[DBG100]] = !DILocation(line: 34, column: 7, scope: [[DBG21]])
-// SIMD: [[DBG101]] = !DILocation(line: 34, column: 5, scope: [[DBG21]])
-// SIMD: [[DBG102]] = !DILocation(line: 35, column: 3, scope: [[DBG21]])
+// SIMD: [[META71]] = !DILocalVariable(name: "argc", arg: 1, scope: [[DBG22]], file: [[META3]], line: 20, type: [[META6]])
+// SIMD: [[META72]] = !DILocation(line: 20, column: 13, scope: [[DBG22]])
+// SIMD: [[META73]] = !DILocalVariable(name: "argv", arg: 2, scope: [[DBG22]], file: [[META3]], line: 20, type: [[META7]])
+// SIMD: [[META74]] = !DILocation(line: 20, column: 26, scope: [[DBG22]])
+// SIMD: [[META75]] = !DILocalVariable(name: "b", scope: [[DBG22]], file: [[META3]], line: 21, type: [[META6]])
+// SIMD: [[META76]] = !DILocation(line: 21, column: 5, scope: [[DBG22]])
+// SIMD: [[DBG77]] = !DILocation(line: 21, column: 9, scope: [[DBG22]])
+// SIMD: [[META78]] = !DILocalVariable(name: "c", scope: [[DBG22]], file: [[META3]], line: 21, type: [[META6]])
+// SIMD: [[META79]] = !DILocation(line: 21, column: 15, scope: [[DBG22]])
+// SIMD: [[META80]] = !DILocalVariable(name: "d", scope: [[DBG22]], file: [[META3]], line: 21, type: [[META6]])
+// SIMD: [[META81]] = !DILocation(line: 21, column: 18, scope: [[DBG22]])
+// SIMD: [[META82]] = !DILocalVariable(name: "e", scope: [[DBG22]], file: [[META3]], line: 21, type: [[META6]])
+// SIMD: [[META83]] = !DILocation(line: 21, column: 21, scope: [[DBG22]])
+// SIMD: [[META84]] = !DILocalVariable(name: "f", scope: [[DBG22]], file: [[META3]], line: 21, type: [[META6]])
+// SIMD: [[META85]] = !DILocation(line: 21, column: 24, scope: [[DBG22]])
+// SIMD: [[META86]] = !DILocalVariable(name: "g", scope: [[DBG22]], file: [[META3]], line: 21, type: [[META6]])
+// SIMD: [[META87]] = !DILocation(line: 21, column: 27, scope: [[DBG22]])
+// SIMD: [[META88]] = !DILocalVariable(name: "str1", scope: [[DBG22]], file: [[META3]], line: 23, type: [[META15]])
+// SIMD: [[META89]] = !DILocation(line: 23, column: 14, scope: [[DBG22]])
+// SIMD: [[META90]] = !DILocalVariable(name: "str2", scope: [[DBG22]], file: [[META3]], line: 24, type: [[META53]])
+// SIMD: [[META91]] = !DILocation(line: 24, column: 15, scope: [[DBG22]])
+// SIMD: [[META92]] = !DILocalVariable(name: "str3", scope: [[DBG22]], file: [[META3]], line: 25, type: [[META56]])
+// SIMD: [[META93]] = !DILocation(line: 25, column: 8, scope: [[DBG22]])
+// SIMD: [[META94]] = !DILocalVariable(name: "str4", scope: [[DBG22]], file: [[META3]], line: 26, type: [[META8]])
+// SIMD: [[META95]] = !DILocation(line: 26, column: 9, scope: [[DBG22]])
+// SIMD: [[DBG96]] = !DILocation(line: 26, column: 16, scope: [[DBG22]])
+// SIMD: [[META97]] = !DILocalVariable(name: "str5", scope: [[DBG22]], file: [[META3]], line: 27, type: [[META62]])
+// SIMD: [[META98]] = !DILocation(line: 27, column: 16, scope: [[DBG22]])
+// SIMD: [[DBG99]] = !DILocation(line: 27, column: 23, scope: [[DBG22]])
+// SIMD: [[DBG100]] = !DILocation(line: 34, column: 7, scope: [[DBG22]])
+// SIMD: [[DBG101]] = !DILocation(line: 34, column: 5, scope: [[DBG22]])
+// SIMD: [[DBG102]] = !DILocation(line: 35, column: 3, scope: [[DBG22]])
 // SIMD: [[META103]] = !DILocalVariable(name: "b", scope: [[META104:![0-9]+]], file: [[META3]], line: 43, type: [[META6]])
-// SIMD: [[META104]] = distinct !DILexicalBlock(scope: [[DBG21]], file: [[META3]], line: 42, column: 3)
+// SIMD: [[META104]] = distinct !DILexicalBlock(scope: [[DBG22]], file: [[META3]], line: 42, column: 3)
 // SIMD: [[META105]] = !DILocation(line: 43, column: 9, scope: [[META104]])
 // SIMD: [[META106]] = !DILocalVariable(name: "c", scope: [[META104]], file: [[META3]], line: 44, type: [[META6]])
 // SIMD: [[META107]] = !DILocation(line: 44, column: 7, scope: [[META104]])
@@ -737,6 +738,6 @@ int main (int argc, char **argv) {
 // SIMD: [[DBG109]] = !DILocation(line: 45, column: 13, scope: [[META104]])
 // SIMD: [[DBG110]] = !DILocation(line: 45, column: 11, scope: [[META104]])
 // SIMD: [[DBG111]] = !DILocation(line: 45, column: 7, scope: [[META104]])
-// SIMD: [[DBG112]] = !DILocation(line: 53, column: 3, scope: [[DBG21]])
-// SIMD: [[DBG113]] = !DILocation(line: 54, column: 1, scope: [[DBG21]])
+// SIMD: [[DBG112]] = !DILocation(line: 53, column: 3, scope: [[DBG22]])
+// SIMD: [[DBG113]] = !DILocation(line: 54, column: 1, scope: [[DBG22]])
 //.
diff --git a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
index 389581c376a6d..11de7802ec300 100644
--- a/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
+++ b/flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
@@ -604,7 +604,7 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp,
   }
 
   auto addTargetOpDISP = [&](bool lineTableOnly,
-                             llvm::ArrayRef<mlir::LLVM::DINodeAttr> entities) {
+                             llvm::ArrayRef<mlir::Attribute> entities) {
     // When we process the DeclareOp inside the OpenMP target region, all the
     // variables get the DISubprogram of the parent function of the target op as
     // the scope. In the codegen (to llvm ir), OpenMP target op results in the
@@ -656,8 +656,8 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp,
 
       // Make sure that information about the imported modules is copied in the
       // new function.
-      llvm::SmallVector<mlir::LLVM::DINodeAttr> opEntities;
-      for (mlir::LLVM::DINodeAttr N : entities) {
+      llvm::SmallVector<mlir::Attribute> opEntities;
+      for (mlir::Attribute N : entities) {
         if (auto entity = mlir::dyn_cast<mlir::LLVM::DIImportedEntityAttr>(N)) {
           auto importedEntity = mlir::LLVM::DIImportedEntityAttr::get(
               context, entity.getTag(), spAttr, entity.getEntity(),
@@ -695,7 +695,7 @@ void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp,
   });
 
   mlir::LLVM::DISubprogramAttr spAttr;
-  llvm::SmallVector<mlir::LLVM::DINodeAttr> retainedNodes;
+  llvm::SmallVector<mlir::Attribute> retainedNodes;
 
   if (hasUseStmts) {
     mlir::DistinctAttr recId =
diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h
index 9753c363166d9..04c360b57322e 100644
--- a/llvm/include/llvm/IR/DIBuilder.h
+++ b/llvm/include/llvm/IR/DIBuilder.h
@@ -53,7 +53,7 @@ namespace llvm {
     /// Track the RetainTypes, since they can be updated later on.
     SmallVector<TrackingMDNodeRef, 4> AllRetainTypes;
     SmallVector<DISubprogram *, 4> AllSubprograms;
-    SmallVector<Metadata *, 4> AllGVs;
+    SmallVector<Metadata *, 4> Globals;
     SmallVector<TrackingMDNodeRef, 4> ImportedModules;
     /// Map Macro parent (which can be DIMacroFile or nullptr) to a list of
     /// Metadata all of type DIMacroNode.
@@ -64,8 +64,8 @@ namespace llvm {
     SmallVector<TrackingMDNodeRef, 4> UnresolvedNodes;
     bool AllowUnresolvedNodes;
 
-    /// Each subprogram's preserved local variables, labels, imported entities,
-    /// and types.
+    /// Each subprogram's preserved local and static local variables, labels,
+    /// imported entities, and types.
     ///
     /// Do not use a std::vector.  Some versions of libc++ apparently copy
     /// instead of move on grow operations, and TrackingMDRef is expensive to
diff --git a/llvm/include/llvm/IR/DebugInfo.h b/llvm/include/llvm/IR/DebugInfo.h
index cb8f6fa1b132b..dc3ff31449a2f 100644
--- a/llvm/include/llvm/IR/DebugInfo.h
+++ b/llvm/include/llvm/IR/DebugInfo.h
@@ -124,6 +124,7 @@ class DebugInfoFinder {
 
 private:
   void processCompileUnit(DICompileUnit *CU);
+  void processGlobalVariableExpression(DIGlobalVariableExpression *GVE);
   void processScope(DIScope *Scope);
   void processType(DIType *DT);
   void processImportedEntity(const DIImportedEntity *Import);
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index e28b47d87d4e5..ef156c5e5aacf 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -2080,6 +2080,10 @@ class DICompileUnit : public DIScope {
   }
 
 public:
+  constexpr static unsigned GLOBALS_IDX = 6;
+  constexpr static unsigned IMPORTED_ENTITIES_IDX = 7;
+  constexpr static unsigned ENUMS_IDX = 4;
+
   static void get() = delete;
   static void getIfExists() = delete;
 
@@ -2163,10 +2167,12 @@ class DICompileUnit : public DIScope {
   MDString *getRawSplitDebugFilename() const {
     return getOperandAs<MDString>(3);
   }
-  Metadata *getRawEnumTypes() const { return getOperand(4); }
+  Metadata *getRawEnumTypes() const { return getOperand(ENUMS_IDX); }
   Metadata *getRawRetainedTypes() const { return getOperand(5); }
-  Metadata *getRawGlobalVariables() const { return getOperand(6); }
-  Metadata *getRawImportedEntities() const { return getOperand(7); }
+  Metadata *getRawGlobalVariables() const { return getOperand(GLOBALS_IDX); }
+  Metadata *getRawImportedEntities() const {
+    return getOperand(IMPORTED_ENTITIES_IDX);
+  }
   Metadata *getRawMacros() const { return getOperand(8); }
   MDString *getRawSysRoot() const { return getOperandAs<MDString>(9); }
   MDString *getRawSDK() const { return getOperandAs<MDString>(10); }
@@ -2178,14 +2184,14 @@ class DICompileUnit : public DIScope {
   /// DICompileUnit should be fairly rare.
   /// @{
   void replaceEnumTypes(DICompositeTypeArray N) {
-    replaceOperandWith(4, N.get());
+    replaceOperandWith(ENUMS_IDX, N.get());
   }
   void replaceRetainedTypes(DITypeArray N) { replaceOperandWith(5, N.get()); }
   void replaceGlobalVariables(DIGlobalVariableExpressionArray N) {
-    replaceOperandWith(6, N.get());
+    replaceOperandWith(GLOBALS_IDX, N.get());
   }
   void replaceImportedEntities(DIImportedEntityArray N) {
-    replaceOperandWith(7, N.get());
+    replaceOperandWith(IMPORTED_ENTITIES_IDX, N.get());
   }
   void replaceMacros(DIMacroNodeArray N) { replaceOperandWith(8, N.get()); }
   /// @}
@@ -2292,7 +2298,7 @@ class DISubprogram : public DILocalScope {
           unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags,
           DISPFlags SPFlags, DICompileUnit *Unit,
           DITemplateParameterArray TemplateParams, DISubprogram *Declaration,
-          DINodeArray RetainedNodes, DITypeArray ThrownTypes,
+          MDNodeArray RetainedNodes, DITypeArray ThrownTypes,
           DINodeArray Annotations, StringRef TargetFuncName,
           bool UsesKeyInstructions, StorageType Storage,
           bool ShouldCreate = true) {
@@ -2333,7 +2339,7 @@ class DISubprogram : public DILocalScope {
        DIType *ContainingType, unsigned VirtualIndex, int ThisAdjustment,
        DIFlags Flags, DISPFlags SPFlags, DICompileUnit *Unit,
        DITemplateParameterArray TemplateParams = nullptr,
-       DISubprogram *Declaration = nullptr, DINodeArray RetainedNodes = nullptr,
+       DISubprogram *Declaration = nullptr, MDNodeArray RetainedNodes = nullptr,
        DITypeArray ThrownTypes = nullptr, DINodeArray Annotations = nullptr,
        StringRef TargetFuncName = "", bool UsesKeyInstructions = false),
       (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType,
@@ -2462,7 +2468,7 @@ class DISubprogram : public DILocalScope {
     return cast_or_null<DISubprogram>(getRawDeclaration());
   }
   void replaceDeclaration(DISubprogram *Decl) { replaceOperandWith(6, Decl); }
-  DINodeArray getRetainedNodes() const {
+  MDNodeArray getRetainedNodes() const {
     return cast_or_null<MDTuple>(getRawRetainedNodes());
   }
   DITypeArray getThrownTypes() const {
@@ -2501,19 +2507,24 @@ class DISubprogram : public DILocalScope {
   void replaceRawLinkageName(MDString *LinkageName) {
     replaceOperandWith(3, LinkageName);
   }
-  void replaceRetainedNodes(DINodeArray N) {
-    replaceOperandWith(7, N.get());
+  void replaceRetainedNodes(MDNodeArray N) { replaceOperandWith(7, N.get()); }
+
+  template <typename IterT> void retainNodes(IterT NodesBegin, IterT NodesEnd) {
+    auto RetainedNodes = getRetainedNodes();
+    SmallVector<Metadata *> MDs(RetainedNodes.begin(), RetainedNodes.end());
+    MDs.append(NodesBegin, NodesEnd);
+    replaceRetainedNodes(MDNode::get(getContext(), MDs));
   }
 
   /// For the given retained node of DISubprogram, applies one of the
   /// given functions depending on the type of the node.
   template <typename T, typename MetadataT, typename FuncLVT,
             typename FuncLabelT, typename FuncImportedEntityT,
-            typename FuncTypeT, typename FuncUnknownT>
+            typename FuncTypeT, typename FuncGVET, typename FuncUnknownT>
   static T visitRetainedNode(MetadataT *N, FuncLVT &&FuncLV,
                              FuncLabelT &&FuncLabel,
                              FuncImportedEntityT &&FuncIE, FuncTypeT &&FuncType,
-                             FuncUnknownT &&FuncUnknown) {
+                             FuncGVET &&FuncGVE, FuncUnknownT &&FuncUnknown) {
     static_assert(std::is_base_of_v<Metadata, MetadataT>,
                   "N must point to Metadata or const Metadata");
 
@@ -2525,6 +2536,8 @@ class DISubprogram : public DILocalScope {
       return FuncIE(IE);
     if (auto *Ty = dyn_cast<DIType>(N))
       return FuncType(Ty);
+    if (auto *GVE = dyn_cast<DIGlobalVariableExpression>(N))
+      return FuncGVE(GVE);
     return FuncUnknown(N);
   }
 
@@ -2538,12 +2551,13 @@ class DISubprogram : public DILocalScope {
   /// For each retained node, applies one of the given functions depending
   /// on the type of a node.
   template <typename FuncLVT, typename FuncLabelT, typename FuncImportedEntityT,
-            typename FuncTypeT>
+            typename FuncTypeT, typename FuncGVET>
   void forEachRetainedNode(FuncLVT &&FuncLV, FuncLabelT &&FuncLabel,
-                           FuncImportedEntityT &&FuncIE, FuncTypeT &&FuncType) {
+                           FuncImportedEntityT &&FuncIE, FuncTypeT &&FuncType,
+                           FuncGVET &&FuncGVE) {
     for (MDNode *N : getRetainedNodes())
       visitRetainedNode<void>(
-          N, FuncLV, FuncLabel, FuncIE, FuncType,
+          N, FuncLV, FuncLabel, FuncIE, FuncType, FuncGVE,
           [](auto *N) { llvm_unreachable("Unexpected retained node!"); });
   }
 
@@ -2575,6 +2589,17 @@ class DISubprogram : public DILocalScope {
   /// of a current scope for expression evaluation.
   void cleanupRetainedNodes();
 
+  template <typename T> void cleanupRetainedNodesIf(T &&RemovePred) {
+    MDTuple *RetainedNodes = dyn_cast_or_null<MDTuple>(getRawRetainedNodes());
+    // As this is expected to be called during module loading, before
+    // stripping old or incorrect debug info, perform minimal sanity check.
+    if (!RetainedNodes)
+      return;
+    // replaceRetainedNodes() should not re-unique DISubprogram if new list is
+    // the same pointer.
+    replaceRetainedNodes(RetainedNodes->filter(RemovePred));
+  }
+
   /// Calls SP->cleanupRetainedNodes() for a range of DISubprograms.
   template <typename RangeT>
   static void cleanupRetainedNodes(const RangeT &NewDistinctSPs) {
@@ -4780,6 +4805,24 @@ class DebugVariableAggregate : public DebugVariable {
 template <>
 struct DenseMapInfo<DebugVariableAggregate>
     : public DenseMapInfo<DebugVariable> {};
+
+template <typename NodeT> static const DIScope *getScope(const NodeT *N) {
+  return N->getScope();
+}
+
+template <typename NodeT> static DIScope *getScope(NodeT *N) {
+  return N->getScope();
+}
+
+template <>
+[[maybe_unused]] const DIScope *
+getScope<>(const DIGlobalVariableExpression *N) {
+  return N->getVariable()->getScope();
+}
+template <>
+[[maybe_unused]] DIScope *getScope<>(DIGlobalVariableExpression *N) {
+  return N->getVariable()->getScope();
+}
 } // end namespace llvm
 
 #undef DEFINE_MDNODE_GET_UNPACK_IMPL
diff --git a/llvm/include/llvm/IR/Metadata.h b/llvm/include/llvm/IR/Metadata.h
index f6c393c1d8c67..b2f088c2eaa93 100644
--- a/llvm/include/llvm/IR/Metadata.h
+++ b/llvm/include/llvm/IR/Metadata.h
@@ -1564,6 +1564,28 @@ class MDTuple : public MDNode {
   /// Shrink the operands by 1.
   void pop_back() { resize(getNumOperands() - 1); }
 
+  /// Filter out tuple elements that satisfy predicate.
+  /// Return this if no elements should be filtered out (without re-uniquing).
+  template <typename T> MDTuple *filter(T &&RemovePred) {
+    ArrayRef<MDOperand> Ops = operands();
+    // Find first node to be removed from the tuple.
+    auto FirstToRemove = find_if(Ops, RemovePred);
+
+    // Exit if no nodes should be removed.
+    if (FirstToRemove == Ops.end())
+      return this;
+
+    // Copy all nodes before the first removed.
+    SmallVector<Metadata *> MDs(Ops.begin(), FirstToRemove);
+    MDs.reserve(Ops.size());
+
+    // Filter the rest of the nodes
+    std::copy_if(FirstToRemove + 1, Ops.end(), std::back_inserter(MDs),
+                 [&](Metadata *N) { return !RemovePred(N); });
+
+    return get(getContext(), MDs);
+  }
+
   static bool classof(const Metadata *MD) {
     return MD->getMetadataID() == MDTupleKind;
   }
diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index 4bc55232a6df6..c6351b77ddfd9 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -545,85 +545,62 @@ class MetadataLoader::MetadataLoaderImpl {
                llvm::dyn_cast_or_null<DISubprogram>(S);
   }
 
-  /// Move local imports from DICompileUnit's 'imports' field to
-  /// DISubprogram's retainedNodes.
-  /// Move function-local enums from DICompileUnit's enums
-  /// to DISubprogram's retainedNodes.
+  /// Map SP -> {Metadata} to store CU locals that should be attached to
+  /// subprogram retainedNodes list during CU upgrade.
+  using SPToEntitiesMap =
+      SmallDenseMap<DISubprogram *, SmallVector<Metadata *>>;
+
+  /// Retrieve the CU operand at position ListIndex, treat it as an MDTuple, and
+  /// remove all local debug info nodes from it. Fill SPToEntities map with
+  /// removed local nodes.
+  template <typename NodeT>
+  void upgradeOneCULocalsList(SPToEntitiesMap &SPToEntities, DICompileUnit *CU,
+                              unsigned ListIndex) {
+    MDTuple *List = cast_if_present<MDTuple>(CU->getOperand(ListIndex));
+    if (!List)
+      return;
+
+    CU->replaceOperandWith(ListIndex, List->filter([&](Metadata *N) {
+      DILocalScope *LS =
+          dyn_cast_or_null<DILocalScope>(getScope(cast<NodeT>(N)));
+      if (!LS)
+        return false;
+
+      if (auto *SP = findEnclosingSubprogram(LS))
+        SPToEntities[SP].push_back(N);
+
+      return true;
+    }));
+  }
+
+  /// Move function-local entities from DICompileUnit's 'imports',
+  /// 'enums', and 'globals' fields to DISubprogram's retainedNodes.
   void upgradeCULocals() {
     NamedMDNode *CUNodes = TheModule.getNamedMetadata("llvm.dbg.cu");
     if (!CUNodes)
       return;
 
-    // Filter out elements of ToRemove from tuple T.
-    auto FilterTuple = [this](MDNode *T,
-                              const SetVector<Metadata *> &ToRemove) {
-      SmallVector<Metadata *> Result;
-      for (Metadata *Op : T->operands())
-        if (!ToRemove.contains(Op))
-          Result.push_back(Op);
-      return MDTuple::get(Context, Result);
-    };
-
-    // For each CU:
-    // - Collect local metadata nodes from CU's imports: and enums: lists in
-    //   MetadataToRemove set.
-    // - Remove metadata nodes of MetadataToRemove set from CU's imports: and
-    //   enums: lists.
-    // - Group MetadataToRemove items by their parent subprograms (in
-    //   SPToEntities map).
-    // - For each subprogram SP in SPToEntities:
-    //   - Append collected local metadata nodes to SP's retainedNodes: list.
+    SPToEntitiesMap SPToEntities;
     for (MDNode *N : CUNodes->operands()) {
       auto *CU = dyn_cast<DICompileUnit>(N);
       if (!CU)
         continue;
 
-      SetVector<Metadata *> MetadataToRemove;
-      // Collect imported entities to be moved.
-      if (CU->getRawImportedEntities())
-        for (Metadata *Op : CU->getImportedEntities()->operands()) {
-          auto *IE = cast<DIImportedEntity>(Op);
-          if (isa_and_nonnull<DILocalScope>(IE->getScope()))
-            MetadataToRemove.insert(IE);
-        }
-      // Collect enums to be moved.
-      if (CU->getRawEnumTypes())
-        for (Metadata *Op : CU->getEnumTypes()->operands()) {
-          auto *Enum = cast<DICompositeType>(Op);
-          if (isa_and_nonnull<DILocalScope>(Enum->getScope()))
-            MetadataToRemove.insert(Enum);
-        }
-
-      if (MetadataToRemove.empty())
-        continue;
-
-      // Remove entities with local scope from CU.
-      if (CU->getRawImportedEntities())
-        CU->replaceImportedEntities(
-            FilterTuple(CU->getImportedEntities().get(), MetadataToRemove));
-
-      // Remove enums with local scope from CU.
-      if (CU->getRawEnumTypes())
-        CU->replaceEnumTypes(
-            FilterTuple(CU->getEnumTypes().get(), MetadataToRemove));
-
-      // Find DISubprogram corresponding to each entity.
-      SmallDenseMap<DISubprogram *, SmallVector<Metadata *>> SPToEntities;
-      for (auto *I : MetadataToRemove) {
-        DILocalScope *Scope =
-            DISubprogram::getRetainedNodeScope(cast<DINode>(I));
-        if (auto *SP = findEnclosingSubprogram(Scope))
-          SPToEntities[SP].push_back(I);
-      }
-
-      // Update DISubprograms' retainedNodes.
-      for (auto I = SPToEntities.begin(); I != SPToEntities.end(); ++I) {
-        auto *SP = I->first;
-        auto RetainedNodes = SP->getRetainedNodes();
-        SmallVector<Metadata *> MDs(RetainedNodes.begin(), RetainedNodes.end());
-        MDs.append(I->second);
-        SP->replaceRetainedNodes(MDNode::get(Context, MDs));
-      }
+      // Remove all static local variables from CU's globals list.
+      upgradeOneCULocalsList<DIGlobalVariableExpression>(
+          SPToEntities, CU, DICompileUnit::GLOBALS_IDX);
+      // Remove all local imports from CU's imports list.
+      upgradeOneCULocalsList<DIImportedEntity>(
+          SPToEntities, CU, DICompileUnit::IMPORTED_ENTITIES_IDX);
+      // Remove all local types from CU's enums list.
+      upgradeOneCULocalsList<DICompositeType>(SPToEntities, CU,
+                                              DICompileUnit::ENUMS_IDX);
+
+      // Retain local entities removed from the CU in their corresponding
+      // subprograms.
+      for (auto &[SP, Nodes] : SPToEntities)
+        SP->retainNodes(Nodes.begin(), Nodes.end());
+      SPToEntities.clear();
     }
 
     ParentSubprogram.clear();
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 4b6b76c48dcbf..b674a5b7be3dd 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -1466,6 +1466,10 @@ void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) {
   // Grab the variable info that was squirreled away in the MMI side-table.
   collectVariableInfoFromMFTable(Processed);
 
+  for (const MDNode *N : SP->getRetainedNodes())
+    if (const auto *GVE = dyn_cast<DIGlobalVariableExpression>(N))
+      collectGlobalOrStaticLocalVariableInfo(GVE);
+
   for (const auto &I : DbgValues) {
     InlinedEntity IV = I.first;
     if (Processed.count(IV))
@@ -3242,9 +3246,57 @@ void CodeViewDebug::emitDebugInfoForUDTs(
   }
 }
 
+void CodeViewDebug::collectGlobalOrStaticLocalVariableInfo(
+    const DIGlobalVariableExpression *GVE) {
+  const DIGlobalVariable *DIGV = GVE->getVariable();
+  const DIExpression *DIE = GVE->getExpression();
+  // Don't emit string literals in CodeView, as the only useful parts are
+  // generally the filename and line number, which isn't possible to output
+  // in CodeView. String literals should be the only unnamed GlobalVariable
+  // with debug info.
+  if (DIGV->getName().empty())
+    return;
+
+  if ((DIE->getNumElements() == 2) &&
+      (DIE->getElement(0) == dwarf::DW_OP_plus_uconst))
+    // Record the constant offset for the variable.
+    //
+    // A Fortran common block uses this idiom to encode the offset
+    // of a variable from the common block's starting address.
+    CVGlobalVariableOffsets.insert(std::make_pair(DIGV, DIE->getElement(1)));
+
+  // Emit constant global variables in a global symbol section.
+  if (GlobalMap.count(GVE) == 0 && DIE->isConstant()) {
+    CVGlobalVariable CVGV = {DIGV, DIE};
+    GlobalVariables.emplace_back(std::move(CVGV));
+  }
+
+  const auto *GV = GlobalMap.lookup(GVE);
+  if (!GV || GV->isDeclarationForLinker())
+    return;
+
+  DIScope *Scope = DIGV->getScope();
+  SmallVector<CVGlobalVariable, 1> *VariableList;
+  if (Scope && isa<DILocalScope>(Scope)) {
+    // Locate a global variable list for this scope, creating one if
+    // necessary.
+    auto Insertion =
+        ScopeGlobals.insert({Scope, std::unique_ptr<GlobalVariableList>()});
+    if (Insertion.second)
+      Insertion.first->second = std::make_unique<GlobalVariableList>();
+    VariableList = Insertion.first->second.get();
+  } else if (GV->hasComdat()) {
+    // Emit this global variable into a COMDAT section.
+    VariableList = &ComdatVariables;
+  } else {
+    // Emit this global variable in a single global symbol section.
+    VariableList = &GlobalVariables;
+  }
+  CVGlobalVariable CVGV = {DIGV, GV};
+  VariableList->emplace_back(std::move(CVGV));
+}
+
 void CodeViewDebug::collectGlobalVariableInfo() {
-  DenseMap<const DIGlobalVariableExpression *, const GlobalVariable *>
-      GlobalMap;
   for (const GlobalVariable &GV : MMI->getModule()->globals()) {
     SmallVector<DIGlobalVariableExpression *, 1> GVEs;
     GV.getDebugInfo(GVEs);
@@ -3256,51 +3308,7 @@ void CodeViewDebug::collectGlobalVariableInfo() {
   for (const MDNode *Node : CUs->operands()) {
     const auto *CU = cast<DICompileUnit>(Node);
     for (const auto *GVE : CU->getGlobalVariables()) {
-      const DIGlobalVariable *DIGV = GVE->getVariable();
-      const DIExpression *DIE = GVE->getExpression();
-      // Don't emit string literals in CodeView, as the only useful parts are
-      // generally the filename and line number, which isn't possible to output
-      // in CodeView. String literals should be the only unnamed GlobalVariable
-      // with debug info.
-      if (DIGV->getName().empty()) continue;
-
-      if ((DIE->getNumElements() == 2) &&
-          (DIE->getElement(0) == dwarf::DW_OP_plus_uconst))
-        // Record the constant offset for the variable.
-        //
-        // A Fortran common block uses this idiom to encode the offset
-        // of a variable from the common block's starting address.
-        CVGlobalVariableOffsets.insert(
-            std::make_pair(DIGV, DIE->getElement(1)));
-
-      // Emit constant global variables in a global symbol section.
-      if (GlobalMap.count(GVE) == 0 && DIE->isConstant()) {
-        CVGlobalVariable CVGV = {DIGV, DIE};
-        GlobalVariables.emplace_back(std::move(CVGV));
-      }
-
-      const auto *GV = GlobalMap.lookup(GVE);
-      if (!GV || GV->isDeclarationForLinker())
-        continue;
-
-      DIScope *Scope = DIGV->getScope();
-      SmallVector<CVGlobalVariable, 1> *VariableList;
-      if (Scope && isa<DILocalScope>(Scope)) {
-        // Locate a global variable list for this scope, creating one if
-        // necessary.
-        auto Insertion = ScopeGlobals.insert(
-            {Scope, std::unique_ptr<GlobalVariableList>()});
-        if (Insertion.second)
-          Insertion.first->second = std::make_unique<GlobalVariableList>();
-        VariableList = Insertion.first->second.get();
-      } else if (GV->hasComdat())
-        // Emit this global variable into a COMDAT section.
-        VariableList = &ComdatVariables;
-      else
-        // Emit this global variable in a single global symbol section.
-        VariableList = &GlobalVariables;
-      CVGlobalVariable CVGV = {DIGV, GV};
-      VariableList->emplace_back(std::move(CVGV));
+      collectGlobalOrStaticLocalVariableInfo(GVE);
     }
   }
 }
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
index 7fd2cec8c74f2..ba3cd077a4884 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
@@ -237,6 +237,8 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
   // belong in. A null local scope represents the global scope.
   typedef SmallVector<CVGlobalVariable, 1> GlobalVariableList;
   DenseMap<const DIScope*, std::unique_ptr<GlobalVariableList> > ScopeGlobals;
+  DenseMap<const DIGlobalVariableExpression *, const GlobalVariable *>
+      GlobalMap;
 
   // Array of global variables which  need to be emitted into a COMDAT section.
   SmallVector<CVGlobalVariable, 1> ComdatVariables;
@@ -389,6 +391,8 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
   using InlinedEntity = DbgValueHistoryMap::InlinedEntity;
 
   void collectGlobalVariableInfo();
+  void
+  collectGlobalOrStaticLocalVariableInfo(const DIGlobalVariableExpression *GVE);
   void collectVariableInfo(const DISubprogram *SP);
 
   void collectVariableInfoFromMFTable(DenseSet<InlinedEntity> &Processed);
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 72022fcddf316..44fed8d966df3 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -1518,6 +1518,8 @@ void DwarfDebug::endModule() {
     DenseSet<DIGlobalVariable *> Processed;
     for (auto *GVE : CUNode->getGlobalVariables()) {
       DIGlobalVariable *GV = GVE->getVariable();
+      assert(!isa_and_nonnull<DILocalScope>(GV->getScope()) &&
+             "Unexpected function-local entity in 'globals' CU field.");
       if (Processed.insert(GV).second)
         CU->getOrCreateGlobalVariableDIE(GV, sortGlobalExprs(GVMap[GV]));
     }
@@ -1530,14 +1532,20 @@ void DwarfDebug::endModule() {
     }
 
     // Emit function-local entities.
-    for (const auto *D : CU->getDeferredLocalDecls()) {
-      if (auto *IE = dyn_cast<DIImportedEntity>(D))
-        CU->getOrCreateImportedEntityDIE(IE);
-      else if (auto *Ty = dyn_cast<DIType>(D))
-        CU->getOrCreateTypeDIE(Ty);
-      else
-        llvm_unreachable("Unexpected local retained node!");
-    }
+    const auto Unexpected = [](const Metadata *N) {
+      llvm_unreachable("Unexpected local retained node!");
+    };
+    for (const auto *D : CU->getDeferredLocalDecls())
+      DISubprogram::visitRetainedNode<void>(
+          D, Unexpected, Unexpected,
+          [CU](const auto *IE) { CU->getOrCreateImportedEntityDIE(IE); },
+          [CU](const auto *Ty) { CU->getOrCreateTypeDIE(Ty); },
+          [&](const auto *GVE) {
+            DIGlobalVariable *GV = GVE->getVariable();
+            if (Processed.insert(GV).second)
+              CU->getOrCreateGlobalVariableDIE(GV, sortGlobalExprs(GVMap[GV]));
+          },
+          Unexpected);
 
     // Emit base types.
     CU->createBaseTypeDIEs();
@@ -2084,16 +2092,17 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU,
   }
 
   // Collect info for retained nodes.
-  for (const DINode *DN : SP->getRetainedNodes()) {
-    const auto *LS = getRetainedNodeScope(DN);
-    if (isa<DILocalVariable>(DN) || isa<DILabel>(DN)) {
+  for (const MDNode *N : SP->getRetainedNodes()) {
+    const auto *LS = getRetainedNodeScope(N);
+    if (isa<DILocalVariable>(N) || isa<DILabel>(N)) {
+      auto *DN = cast<DINode>(N);
       if (!Processed.insert(InlinedEntity(DN, nullptr)).second)
         continue;
       LexicalScope *LexS = LScopes.findLexicalScope(LS);
       if (LexS)
         createConcreteEntity(TheCU, *LexS, DN, nullptr);
     } else {
-      LocalDeclsPerLS[LS].insert(DN);
+      LocalDeclsPerLS[LS].insert(N);
     }
   }
 }
@@ -2893,12 +2902,13 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) {
 #endif
   for (LexicalScope *AScope : LScopes.getAbstractScopesList()) {
     const auto *SP = cast<DISubprogram>(AScope->getScopeNode());
-    for (const DINode *DN : SP->getRetainedNodes()) {
-      const auto *LS = getRetainedNodeScope(DN);
+    for (const MDNode *N : SP->getRetainedNodes()) {
+      const auto *LS = getRetainedNodeScope(N);
       // Ensure LexicalScope is created for the scope of this node.
       auto *LexS = LScopes.getOrCreateAbstractScope(LS);
       assert(LexS && "Expected the LexicalScope to be created.");
-      if (isa<DILocalVariable>(DN) || isa<DILabel>(DN)) {
+      if (isa<DILocalVariable>(N) || isa<DILabel>(N)) {
+        auto *DN = cast<DINode>(N);
         // Collect info for variables/labels that were optimized out.
         if (!Processed.insert(InlinedEntity(DN, nullptr)).second ||
             TheCU.getExistingAbstractEntity(DN))
@@ -2906,7 +2916,7 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) {
         TheCU.createAbstractEntity(DN, LexS);
       } else {
         // Remember the node if this is a local declarations.
-        LocalDeclsPerLS[LS].insert(DN);
+        LocalDeclsPerLS[LS].insert(N);
       }
       assert(
           LScopes.getAbstractScopesList().size() == NumAbstractSubprograms &&
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index 9cb5b63d885d4..d2fa4a3e1e92a 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -33,7 +33,7 @@ DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes, DICompileUnit *CU)
     if (const auto &RTs = CUNode->getRetainedTypes())
       AllRetainTypes.assign(RTs.begin(), RTs.end());
     if (const auto &GVs = CUNode->getGlobalVariables())
-      AllGVs.assign(GVs.begin(), GVs.end());
+      Globals.assign(GVs.begin(), GVs.end());
     if (const auto &IMs = CUNode->getImportedEntities())
       ImportedModules.assign(IMs.begin(), IMs.end());
     if (const auto &MNs = CUNode->getMacros())
@@ -103,8 +103,8 @@ void DIBuilder::finalize() {
     if (auto *SP = dyn_cast<DISubprogram>(N))
       finalizeSubprogram(SP);
 
-  if (!AllGVs.empty())
-    CUNode->replaceGlobalVariables(MDTuple::get(VMContext, AllGVs));
+  if (!Globals.empty())
+    CUNode->replaceGlobalVariables(MDTuple::get(VMContext, Globals));
 
   if (!ImportedModules.empty())
     CUNode->replaceImportedEntities(MDTuple::get(
@@ -932,7 +932,10 @@ DIGlobalVariableExpression *DIBuilder::createGlobalVariableExpression(
   if (!Expr)
     Expr = createExpression();
   auto *N = DIGlobalVariableExpression::get(VMContext, GV, Expr);
-  AllGVs.push_back(N);
+  if (isa_and_nonnull<DILocalScope>(Context))
+    getSubprogramNodesTrackingVector(Context).emplace_back(N);
+  else
+    Globals.push_back(N);
   return N;
 }
 
diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp
index d27c3a9a1548a..e5ae3d034c11f 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -197,13 +197,8 @@ void DebugInfoFinder::processModule(const Module &M) {
 void DebugInfoFinder::processCompileUnit(DICompileUnit *CU) {
   if (!addCompileUnit(CU))
     return;
-  for (auto *DIG : CU->getGlobalVariables()) {
-    if (!addGlobalVariable(DIG))
-      continue;
-    auto *GV = DIG->getVariable();
-    processScope(GV->getScope());
-    processType(GV->getType());
-  }
+  for (auto *GVE : CU->getGlobalVariables())
+    processGlobalVariableExpression(GVE);
   for (auto *ET : CU->getEnumTypes())
     processType(ET);
   for (auto *RT : CU->getRetainedTypes())
@@ -217,6 +212,15 @@ void DebugInfoFinder::processCompileUnit(DICompileUnit *CU) {
     processMacroNode(Macro, nullptr);
 }
 
+void DebugInfoFinder::processGlobalVariableExpression(
+    DIGlobalVariableExpression *GVE) {
+  if (!addGlobalVariable(GVE))
+    return;
+  auto *GV = GVE->getVariable();
+  processScope(GV->getScope());
+  processType(GV->getType());
+}
+
 void DebugInfoFinder::processInstruction(const Module &M,
                                          const Instruction &I) {
   if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&I))
@@ -359,7 +363,8 @@ void DebugInfoFinder::processSubprogram(DISubprogram *SP) {
   SP->forEachRetainedNode(
       [this](DILocalVariable *LV) { processVariable(LV); }, [](DILabel *L) {},
       [this](DIImportedEntity *IE) { processImportedEntity(IE); },
-      [this](DIType *T) { processType(T); });
+      [this](DIType *T) { processType(T); },
+      [this](auto *GVE) { return processGlobalVariableExpression(GVE); });
 }
 
 void DebugInfoFinder::processVariable(const DILocalVariable *DV) {
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index 5db2c86aafc3d..68b7aec5139c3 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -1447,11 +1447,10 @@ bool DISubprogram::describes(const Function *F) const {
 
 template <typename ScopeT, typename NodeT>
 static ScopeT getRawRetainedNodeScopeInternal(NodeT *N) {
-  auto getScope = [](auto *N) { return N->getScope(); };
-
+  auto getScopeLambda = [](auto *N) { return getScope(N); };
   return DISubprogram::visitRetainedNode<ScopeT>(
-      N, getScope, getScope, getScope, getScope,
-      [](auto *N) { return nullptr; });
+      N, getScopeLambda, getScopeLambda, getScopeLambda, getScopeLambda,
+      getScopeLambda, [](auto *N) { return nullptr; });
 }
 
 const DIScope *DISubprogram::getRawRetainedNodeScope(const MDNode *N) {
@@ -1473,7 +1472,7 @@ DILocalScope *DISubprogram::getRetainedNodeScope(MDNode *N) {
 void DISubprogram::cleanupRetainedNodes() {
   // Checks if a metadata node from retainedTypes is a type not belonging to
   // this subprogram.
-  auto IsAlienType = [this](DINode *N) {
+  auto IsAlienType = [this](Metadata *N) {
     auto *T = dyn_cast_or_null<DIType>(N);
     if (!T)
       return false;
@@ -1486,26 +1485,7 @@ void DISubprogram::cleanupRetainedNodes() {
     return this != TypeSP;
   };
 
-  // As this is expected to be called during module loading, before
-  // stripping old or incorrect debug info, perform minimal sanity check.
-  if (!isa_and_present<MDTuple>(getRawRetainedNodes()))
-    return;
-
-  MDTuple *RetainedNodes = cast<MDTuple>(getRawRetainedNodes());
-  SmallVector<Metadata *> MDs;
-  MDs.reserve(RetainedNodes->getNumOperands());
-  for (const MDOperand &Node : RetainedNodes->operands()) {
-    // Ignore malformed retainedNodes.
-    if (Node && !isa<DINode>(Node))
-      return;
-
-    auto *N = cast_or_null<DINode>(Node);
-    if (!IsAlienType(N))
-      MDs.push_back(N);
-  }
-
-  if (MDs.size() != RetainedNodes->getNumOperands())
-    replaceRetainedNodes(MDNode::get(getContext(), MDs));
+  cleanupRetainedNodesIf(IsAlienType);
 }
 
 DILexicalBlockBase::DILexicalBlockBase(LLVMContext &C, unsigned ID,
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index abda69304b7e4..4ac4d2efb4d80 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1594,8 +1594,12 @@ void Verifier::visitDICompileUnit(const DICompileUnit &N) {
   if (auto *Array = N.getRawGlobalVariables()) {
     CheckDI(isa<MDTuple>(Array), "invalid global variable list", &N, Array);
     for (Metadata *Op : N.getGlobalVariables()->operands()) {
-      CheckDI(Op && (isa<DIGlobalVariableExpression>(Op)),
-              "invalid global variable ref", &N, Op);
+      auto *GVE = dyn_cast_or_null<DIGlobalVariableExpression>(Op);
+      CheckDI(GVE, "invalid global variable ref", &N, Op);
+      CheckDI(!isa_and_nonnull<DILocalScope>(GVE->getVariable()->getScope()),
+              "function-local variables are not allowed in a DICompileUnit's "
+              "global variables list",
+              &N, Op);
     }
   }
   if (auto *Array = N.getRawImportedEntities()) {
@@ -1645,13 +1649,13 @@ void Verifier::visitDISubprogram(const DISubprogram &N) {
       auto True = [](const Metadata *) { return true; };
       auto False = [](const Metadata *) { return false; };
       bool IsTypeCorrect = DISubprogram::visitRetainedNode<bool>(
-          Op, True, True, True, True, False);
+          Op, True, True, True, True, True, False);
       CheckDI(IsTypeCorrect,
               "invalid retained nodes, expected DILocalVariable, DILabel, "
-              "DIImportedEntity or DIType",
+              "DIImportedEntity, DIType or DIGlobalVariableExpression",
               &N, Node, Op);
 
-      auto *RetainedNode = cast<DINode>(Op);
+      auto *RetainedNode = cast<MDNode>(Op);
       auto *RetainedNodeScope = dyn_cast_or_null<DILocalScope>(
           DISubprogram::getRawRetainedNodeScope(RetainedNode));
       CheckDI(RetainedNodeScope,
diff --git a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
index 81303faf77b58..b99fb53c8761a 100644
--- a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
+++ b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
@@ -208,7 +208,7 @@ bool BPFAbstractMemberAccess::run(Function &F) {
   if (SP && SP->isDefinition()) {
     for (DIType *Ty: SP->getType()->getTypeArray())
       CheckAnonRecordType(nullptr, Ty);
-    for (const DINode *DN : SP->getRetainedNodes()) {
+    for (const MDNode *DN : SP->getRetainedNodes()) {
       if (const auto *DV = dyn_cast<DILocalVariable>(DN))
         CheckAnonRecordType(nullptr, DV->getType());
     }
diff --git a/llvm/lib/Target/BPF/BTFDebug.cpp b/llvm/lib/Target/BPF/BTFDebug.cpp
index 46a1df28b8f1d..043f6f67c3467 100644
--- a/llvm/lib/Target/BPF/BTFDebug.cpp
+++ b/llvm/lib/Target/BPF/BTFDebug.cpp
@@ -673,7 +673,7 @@ uint32_t BTFDebug::processDISubprogram(const DISubprogram *SP,
   uint32_t FuncId = addType(std::move(FuncTypeEntry));
 
   // Process argument annotations.
-  for (const DINode *DN : SP->getRetainedNodes()) {
+  for (const MDNode *DN : SP->getRetainedNodes()) {
     if (const auto *DV = dyn_cast<DILocalVariable>(DN)) {
       uint32_t Arg = DV->getArg();
       if (Arg)
@@ -1324,7 +1324,7 @@ void BTFDebug::beginFunctionImpl(const MachineFunction *MF) {
   // Use RetainedNodes so we can collect all argument names
   // even if the argument is not used.
   std::unordered_map<uint32_t, StringRef> FuncArgNames;
-  for (const DINode *DN : SP->getRetainedNodes()) {
+  for (const MDNode *DN : SP->getRetainedNodes()) {
     if (const auto *DV = dyn_cast<DILocalVariable>(DN)) {
       // Collect function arguments for subprogram func type.
       uint32_t Arg = DV->getArg();
diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
index 83b40ee927b51..1ccb7a877b2b9 100644
--- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
@@ -743,11 +743,7 @@ static void buildFrameDebugInfo(Function &F, coro::Shape &Shape,
   // If we don't add __coro_frame to the RetainedNodes, user may get
   // `no symbol __coro_frame in context` rather than `__coro_frame`
   // is optimized out, which is more precise.
-  auto RetainedNodes = DIS->getRetainedNodes();
-  SmallVector<Metadata *, 32> RetainedNodesVec(RetainedNodes.begin(),
-                                               RetainedNodes.end());
-  RetainedNodesVec.push_back(FrameDIVar);
-  DIS->replaceOperandWith(7, (MDTuple::get(F.getContext(), RetainedNodesVec)));
+  DIS->retainNodes(&FrameDIVar, &FrameDIVar + 1);
 
   // Construct the location for the frame debug variable. The column number
   // is fake but it should be fine.
diff --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
index dabd495cddd49..3ad9cad9c5e30 100644
--- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
+++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
@@ -1724,6 +1724,7 @@ InstrLowerer::getOrCreateRegionCounters(InstrProfCntrInstBase *Inc) {
           /*Decl=*/nullptr, /*TemplateParams=*/nullptr, /*AlignInBits=*/0,
           Annotations);
       CounterPtr->addDebugInfo(DICounter);
+      DB.finalizeSubprogram(SP);
       DB.finalize();
     }
 
diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp
index 031ce978d21ce..21ae2d59429df 100644
--- a/llvm/lib/Transforms/Utils/CloneFunction.cpp
+++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp
@@ -104,6 +104,12 @@ createIdentityMDPredicate(const Function &F, CloneFunctionChangeType Changes) {
       if (auto *S = dyn_cast_or_null<DILocalScope>(DV->getScope()))
         return ShouldKeep(S->getSubprogram());
 
+    // DIGlobalVariableExpression representing static local variable may be
+    // encountered in DISubprogram's retainedNodes list. Do not remap it, and
+    // remove it from retainedNodes after mapping.
+    if (isa<DIGlobalVariableExpression>(MD))
+      return true;
+
     // Clone types that are local to subprograms being cloned.
     // Avoid cloning other types.
     auto *Type = dyn_cast<DIType>(MD);
@@ -350,6 +356,15 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
                         NameSuffix, CodeInfo, TypeMapper, Materializer,
                         &IdentityMD);
 
+  // DIGlobalVariableExpressions representing static locals stay in the scope of
+  // OldSP after function cloning. Remove them from retainedNodes of NewSP.
+  if (DISubprogram *NewSP = NewFunc->getSubprogram())
+    NewSP->cleanupRetainedNodesIf([NewSP](Metadata *N) {
+      auto *GVE = dyn_cast_or_null<DIGlobalVariableExpression>(N);
+      return GVE &&
+             DISubprogram::getRetainedNodeScope(GVE)->getSubprogram() != NewSP;
+    });
+
   // Only update !llvm.dbg.cu for DifferentModule (not CloneModule). In the
   // same module, the compile unit will already be listed (or not). When
   // cloning a module, CloneModule() will handle creating the named metadata.
diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp b/llvm/lib/Transforms/Utils/Debugify.cpp
index 2923633f29d7a..bd98cefa4c490 100644
--- a/llvm/lib/Transforms/Utils/Debugify.cpp
+++ b/llvm/lib/Transforms/Utils/Debugify.cpp
@@ -393,7 +393,7 @@ bool llvm::collectDebugInfoMetadata(Module &M,
     DebugInfoBeforePass.DIFunctions.insert({&F, SP});
     if (SP) {
       LLVM_DEBUG(dbgs() << "  Collecting subprogram: " << *SP << '\n');
-      for (const DINode *DN : SP->getRetainedNodes()) {
+      for (const MDNode *DN : SP->getRetainedNodes()) {
         if (const auto *DV = dyn_cast<DILocalVariable>(DN)) {
           DebugInfoBeforePass.DIVariables[DV] = 0;
         }
@@ -638,7 +638,7 @@ bool llvm::checkDebugInfoMetadata(Module &M,
 
     if (SP) {
       LLVM_DEBUG(dbgs() << "  Collecting subprogram: " << *SP << '\n');
-      for (const DINode *DN : SP->getRetainedNodes()) {
+      for (const MDNode *DN : SP->getRetainedNodes()) {
         if (const auto *DV = dyn_cast<DILocalVariable>(DN)) {
           DebugInfoAfterPass.DIVariables[DV] = 0;
         }
diff --git a/llvm/test/Bitcode/DIModule-fortran-external-module.ll b/llvm/test/Bitcode/DIModule-fortran-external-module.ll
index 5ca6031d6a1e3..c41e38d9bc136 100644
--- a/llvm/test/Bitcode/DIModule-fortran-external-module.ll
+++ b/llvm/test/Bitcode/DIModule-fortran-external-module.ll
@@ -41,12 +41,11 @@ attributes #1 = { nofree nosync nounwind readnone speculatable willreturn }
 !3 = !DIFile(filename: "em.f90", directory: "tests")
 !4 = !DISubroutineType(types: !5)
 !5 = !{null}
-!6 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 21.0-2165", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !7, globals: !8, imports: !7, splitDebugInlining: false, nameTableKind: None)
+!6 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 21.0-2165", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !7, globals: !7, imports: !7, splitDebugInlining: false, nameTableKind: None)
 !7 = !{}
-!8 = !{!0}
 !10 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !2, entity: !11, file: !3, line: 2)
 !11 = !DIModule(scope: !2, name: "external_module", isDecl: true)
-!12 = !{!10, !13}
+!12 = !{!0, !10, !13}
 !13 = !DILocalVariable(name: "x", scope: !2, file: !3, line: 5, type: !14)
 !14 = !DIBasicType(name: "REAL*4", size: 32, encoding: DW_ATE_float)
 !15 = !{i32 2, !"Debug Info Version", i32 3}
diff --git a/llvm/test/Bitcode/upgrade-cu-static-locals.ll b/llvm/test/Bitcode/upgrade-cu-static-locals.ll
new file mode 100644
index 0000000000000..54757b15642a0
--- /dev/null
+++ b/llvm/test/Bitcode/upgrade-cu-static-locals.ll
@@ -0,0 +1,108 @@
+; Test moving of local static variables from DICompileUnit 'globals' to DISubprogram's 'retainedNodes'
+;
+; RUN: llvm-dis -o - %s.bc | FileCheck %s
+
+; Function Attrs: norecurse nounwind
+define dso_local i32 @foo() local_unnamed_addr #0 !dbg !2 {
+  ret i32 0
+}
+
+define dso_local i32 @abc() local_unnamed_addr #0 !dbg !31 {
+  ret i32 0
+}
+
+define dso_local i32 @xyz() local_unnamed_addr #0 !dbg !32 {
+  ret i32 0
+}
+
+attributes #0 = { noinline optnone }
+
+!llvm.dbg.cu = !{!7, !30}
+!llvm.module.flags = !{!16, !17, !18}
+!llvm.ident = !{!19}
+
+; CHECK: ![[CU:[0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C99, file: ![[F_TEST:[0-9]+]], producer: "clang version 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !{{.*}}, globals: ![[CU_GLOBALS:[0-9]+]]
+; CHECK: ![[CU_GLOBALS]] = !{![[AEXPR:[0-9]+]]}
+; CHECK: ![[AEXPR]] = !DIGlobalVariableExpression(var: ![[A:[0-9]+]]
+; CHECK: ![[A]] = distinct !DIGlobalVariable(name: "a", scope: ![[CU]]
+
+; CHECK: ![[CU30:[0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C99, file: ![[F_TEST2:[0-9]+]], producer: "clang version 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !{{.*}}, globals: ![[CU30_GLOBALS:[0-9]+]]
+; CHECK: ![[CU30_GLOBALS]] = !{![[CAP_A_EXPR:[0-9]+]], ![[CAP_B_EXPR:[0-9]+]]}
+; CHECK: ![[CAP_A_EXPR]] = !DIGlobalVariableExpression(var: ![[CAP_A:[0-9]+]]
+; CHECK: ![[CAP_A]] = distinct !DIGlobalVariable(name: "A", scope: ![[CU30_GLOBALS:[0-9]+]]
+; CHECK: ![[CAP_B_EXPR]] = !DIGlobalVariableExpression(var: ![[CAP_B:[0-9]+]]
+; CHECK: ![[CAP_B]] = distinct !DIGlobalVariable(name: "B", scope: ![[CU30_GLOBALS:[0-9]+]]
+
+; CHECK: ![[FOO:[0-9]+]] = distinct !DISubprogram(name: "foo", scope: ![[F_TEST]], file: ![[F_TEST]], line: 2, type: !{{.*}}, scopeLine: 2, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: ![[CU]], retainedNodes: ![[FOO_RETAINED:[0-9]+]])
+; CHECK: ![[FOO_RETAINED]] = !{![[B_EXPR:[0-9]+]]}
+; CHECK: ![[B_EXPR]] = !DIGlobalVariableExpression(var: ![[B:[0-9]+]]
+; CHECK: ![[B]] = distinct !DIGlobalVariable(name: "b", scope: ![[FOO:[0-9]+]]
+
+; CHECK: ![[ABC:[0-9]+]] = distinct !DISubprogram(name: "abc", scope: ![[CU30]], file: ![[F_TEST2]], line: 2, type: !{{.*}}, scopeLine: 2, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: ![[CU30]], retainedNodes: ![[ABC_RETAINED:[0-9]+]])
+; CHECK: ![[ABC_RETAINED]] = !{![[ABC_A_EXPR:[0-9]+]], ![[ABC_B_EXPR:[0-9]+]]}
+; CHECK: ![[ABC_A_EXPR]] = !DIGlobalVariableExpression(var: ![[ABC_A:[0-9]+]]
+; CHECK: ![[ABC_A]] = distinct !DIGlobalVariable(name: "a", scope: ![[ABC]]
+; CHECK: ![[ABC_B_EXPR]] = !DIGlobalVariableExpression(var: ![[ABC_B:[0-9]+]]
+; CHECK: ![[ABC_B]] = distinct !DIGlobalVariable(name: "b", scope: ![[ABC]]
+
+; CHECK: ![[XYZ:[0-9]+]] = distinct !DISubprogram(name: "xyz", scope: ![[CU30]], file: ![[F_TEST2]], line: 2, type: !{{.*}}, scopeLine: 2, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: ![[CU30]], retainedNodes: ![[XYZ_RETAINED:[0-9]+]])
+; CHECK: ![[XYZ_RETAINED]] = !{![[XYZ_I:[0-9]+]], ![[XYZ_C_EXPR:[0-9]+]]}
+; CHECK: ![[XYZ_I]] = !DILocalVariable(name: "i", arg: 1, scope: ![[XYZ]], file: ![[F_TEST2]]
+; CHECK: ![[XYZ_C_EXPR]] = !DIGlobalVariableExpression(var: ![[XYZ_C:[0-9]+]]
+; CHECK: ![[XYZ_C]] = distinct !DIGlobalVariable(name: "c", scope: ![[XYZ]]
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "b", scope: !2, file: !3, line: 3, type: !14, isLocal: true, isDefinition: true)
+!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !8)
+!3 = !DIFile(filename: "test.c", directory: "/home/yhs/work/tests/llvm/bug")
+!4 = !DISubroutineType(types: !5)
+!5 = !{!6}
+!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !8, globals: !9, nameTableKind: None)
+!8 = !{}
+!9 = !{!0, !10}
+!10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression())
+!11 = distinct !DIGlobalVariable(name: "a", scope: !7, file: !3, line: 1, type: !12, isLocal: true, isDefinition: true)
+!12 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !13)
+!13 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!14 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !15)
+!15 = !DIBasicType(name: "short", size: 16, encoding: DW_ATE_signed)
+!16 = !{i32 2, !"Dwarf Version", i32 4}
+!17 = !{i32 2, !"Debug Info Version", i32 3}
+!18 = !{i32 1, !"wchar_size", i32 4}
+!19 = !{!"clang version 8.0.20181009 "}
+!20 = !DILocation(line: 4, column: 10, scope: !2)
+!21 = !{!22, !22, i64 0}
+!22 = !{!"omnipotent char", !23, i64 0}
+!23 = !{!"Simple C/C++ TBAA"}
+!24 = !DILocation(line: 4, column: 14, scope: !2)
+!25 = !{!26, !26, i64 0}
+!26 = !{!"short", !22, i64 0}
+!27 = !DILocation(line: 4, column: 12, scope: !2)
+
+; Check CU with several global and several local static variables.
+!30 = distinct !DICompileUnit(language: DW_LANG_C99, file: !50, producer: "clang version 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !8, globals: !45, nameTableKind: None)
+
+!31 = distinct !DISubprogram(name: "abc", scope: !30, file: !50, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !30, retainedNodes: !8)
+!32 = distinct !DISubprogram(name: "xyz", scope: !30, file: !50, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !30, retainedNodes: !46)
+
+; Globals
+!33 = !DIGlobalVariableExpression(var: !34, expr: !DIExpression())
+!34 = distinct !DIGlobalVariable(name: "A", scope: !30, file: !50, line: 1, type: !12, isLocal: true, isDefinition: true)
+!35 = !DIGlobalVariableExpression(var: !36, expr: !DIExpression())
+!36 = distinct !DIGlobalVariable(name: "B", scope: !30, file: !50, line: 1, type: !12, isLocal: true, isDefinition: true)
+
+; Static locals of abc
+!37 = !DIGlobalVariableExpression(var: !38, expr: !DIExpression())
+!38 = distinct !DIGlobalVariable(name: "a", scope: !31, file: !50, line: 3, type: !14, isLocal: true, isDefinition: true)
+!39 = !DIGlobalVariableExpression(var: !40, expr: !DIExpression())
+!40 = distinct !DIGlobalVariable(name: "b", scope: !31, file: !50, line: 3, type: !14, isLocal: true, isDefinition: true)
+
+; Locals of xyz
+!41 = !DIGlobalVariableExpression(var: !42, expr: !DIExpression())
+!42 = distinct !DIGlobalVariable(name: "c", scope: !32, file: !50, line: 3, type: !14, isLocal: true, isDefinition: true)
+!43 = !DILocalVariable(name: "i", line: 2, arg: 1, scope: !32, file: !50, type: !14)
+
+!45 = !{!37, !33, !39, !35, !41}
+!46 = !{!43}
+!50 = !DIFile(filename: "test2.c", directory: "/home/yhs/work/tests/llvm/bug")
diff --git a/llvm/test/Bitcode/upgrade-cu-static-locals.ll.bc b/llvm/test/Bitcode/upgrade-cu-static-locals.ll.bc
new file mode 100644
index 0000000000000000000000000000000000000000..1c57ea7cea417e1cf852ee735bd1fae97bc3be0d
GIT binary patch
literal 2732
zcma)84{Q_X761GvcP4S}E|3+Q+}+LuSXKc!JCNA1E!lBkW&_m}I)P|~9mmEgZsOR^
zU)W^Fp_i&*GRzug1IgKt%CxQvEn-xoTWqJ0rUs>`+Zc-?yGbBSDa#6*&_=brGn95(
zHPzC6-+j;Tz3=zE at 4er<CfnG|=1PQ05JD|Ve$9@(zxBTJuk+7TO{{5_=t_`AiBMFE
zP?=PNU_wv9gGZ~6StsP%FiK}QE*Vs=Em5dh`Kv7v<rZnv at v^2?N>`~@sJ>IG(+$}J
z<C^N`<-#y!JuYpXP at JpeY+Hx8_ar*qpz7(Gr{mhgqt74XvJ>F<6%L_Nm{)t{)SFEM
z?@`af5bw-5?4`@r*)Eqf>DDPqe_V}X%Ue089HE^mghHTSWm)^+-|&+}WR}&J3(TCA
zopjL)QRb78^0 at -@mozgmLQjm8PiUA$jre}k$$n&I7e>l+682__$wb*H2`>bkLSGFY
z;e>Ef2vB%;jZmKw0(QLH7wc5u-S98UY3Lg+c2dIStZZh4nH(w47ntj5W?_V$lZZNa
z#3=-mLZ4688yA8q(N)kV3q^!(1s?p|e7eBg<e2F+ee26H1cV-+tm~}M9Vuccg89Pk
zqWKt;Ni+Y)Jl1CyLIEMj3H4J#FfQ~Yg?b+E^~C^5zXczoGf^<7QHGfrDPMr&NZ7oF
znJ&=(6Obg{uMj%-2=x)XuNUvH5js;sPh6;{gnk|m)!=<T*bDz&4US0kQ+C?LX3{i7
z=F4Jx79uRvCxsp!?}xBBg&qL&BrI^1XdB$A1m+b32(8j=CuZ}{ojx&t at 5E_l-S37x
zhfaR_@`?FhH9lNV{_y=@cD}RuHQ~;k&R0KWg+GN>{=|Gnib+retS#^$sS~}tJIf(N
z!9oF#1u4hklPbs at DXhd@6cI`M2IojP5aP<@7)W$%QmL-k9v at z|?pv4Twr^KdHmMUJ
zKL at zphPh4=p~nlfw^Cvrvgrr2!%fAggp!@gTZsIaBJM|sI%N~YfVnn8d-;;0TC6H3
zGf&ve!!mQOcQ_ot4=HfCpFjZb56HTEg#ah0a}~s5oG9>QJ5SCo5larDjv8lXAmcPl
z#>IO1SB#fp#wnZOyv%edW*U?kb4!(waff_(gAcL{Z- at wiIAk$oF5dm11l;ySg#B=J
zs$xneqwDW35qI;%-^YkWUe*G2FgHTyisQ74p48CeQD)MG{UL5MOxO&`;&?HuPuTQB
zGGiiJ3!6S1Fn%aAj%Jlt+JwL!AsC2-eR!`^2t%f)1ogFD<XuF5;vnYY#H at uZaKs{<
zf~$c{XERpzx`v*PveS85EJ_LMRqfP|+8R&Aj5)`e#|MFo=*4 at JJGbADlVSwe7mKB=
zVP?|I_a&?dSi>y2u-!*u`drpHYBNJX9%f8)HscU1v%~L}3Vo1YfCn<G1`j5q&(BiC
z;utaSAnx(i>FZW at uCVe(ftdjScC~RdW<DRQ8qDg4ZH8RdbTMt1$if*-Is5ry(c_)P
z+*kkkGO_3+Kh9%I968UE^BnmP2hmOuvpfOIdwJ|mo|tnG5BTbj7F}X(-6*UCvbm*U
z#x)Gw;DYAsUhcH<lFfWkW=O;gxjmQQ_TjMofYUDY1O)Z_w~4><WFb%7v5<FCuuE1V
z3!TN`Ec=0w0%C;2P|C^Zpw*DiLg>tJQ#s3c3V4XgTiKa3?Oo&MiGp~)BsiJpZJJn@
z3J=+Z{VCya1Z>YGB&Ol4DUsDr*%~38au6}4UGudj7Yk6YrI}}=m8g$H=ncsAAZzDr
zLrV3spw7-!M~9Cc`=B{R)wG(lx~3n*H9yl^4U(<DE*a<L?`q{%UViipLSauRywP3j
z>v+ji+vf|__H+af){4SVt>54MQf*7u0k_}Pet_%t1Ve2d?VNrizfs3)^;(`ca4xsc
z74&v=w6%v at LcWe*ShUn_boci4x4D~KEpBUb4=8ZoePrD10e9TCc5laLk{;2){!m-L
z2k>vb1Oxo|0ZLh|kZ1>}%4$VayKk3YZo$&4<iG%9yFavIm<1cCQXmXfp at b;&?>MGG
zYGr@|ra-p65*ua%@^D}%4h$iW6s@#a8HGQxawF6Siu}G^fpQ9$(M7-h9a at Z_@F%-y
zG4c!gB0A7NtoSc|>WRL8$KNU}^ydgx;Exdm at W%)&C6og3GX4eUcC|9%#dcw`$jP)a
zqfVtwxCJYbs>YfL2WX=g;Q`2^6jz}V-ZqBSRY<3>qGXx8 at -w}TM|zf$6gc+qsKqHd
zr7*9!a26N&lj%eng}snhc*ufxIq~c_rB}wI2#2uM$$R;%Wy|lCvbB5blz-fPl~TTj
zp(~xI8Y4#<lSlTRm6?)98pmSrUS;`F)kVpwh}4vn-o{dhY`5TH3*Mf`UXPTWQVm5_
z6L#l7(B*#XU`VsV7*hYDYRl9(S6yHKoB9(M8s2QYpj%mYVf3xHcfM?zika<4j$VD^
z>e{2P=Z>}~A|(1baP>FfG-aj18sI>@e@`F at btjgLVJbUti@yA*<3axv3sdBlr#8(x
ziQ5jKEOJgHF7md6xIY?+;?S=|M(q`V4MaZK6F8OCpO+ZV#LS7T^dOKk4Lx(3qvu at W
zxDaJCE_w<+Hy)9ID=i`Kb7a9mLSHBwDi))7Dd+=eN at BmkbEY#f<0&9mnK>0R0olg0
zVrO!3k9yV$xplqRzeHK00={+R<Hh%VawG%MSI`^#ih9nXUMB|$27Yw}wR#ZUlB>`&
z5$Qig2|_Qxw;&7ia#><gTtlHkNkVOE8=#2!18reW>)EVp&}j|s22WjGok6>KleWR@
z at wyx844XDLxHj=ETCKLlP+$982uirN+wW?vZT56~{2c*Lu(m63An0oKY;bpN2!&nY
SHuna9huh^3ZS?!a{r&^d3xs0;

literal 0
HcmV?d00001

diff --git a/llvm/test/CodeGen/AArch64/arm64-2011-03-17-AsmPrinterCrash.ll b/llvm/test/CodeGen/AArch64/arm64-2011-03-17-AsmPrinterCrash.ll
index 86658680fdf5a..b5398b1d49520 100644
--- a/llvm/test/CodeGen/AArch64/arm64-2011-03-17-AsmPrinterCrash.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-2011-03-17-AsmPrinterCrash.ll
@@ -28,12 +28,12 @@ attributes #1 = { nounwind readnone }
 !llvm.dbg.cu = !{!0}
 !llvm.module.flags = !{!9, !10}
 
-!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !2)
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
 !1 = !DIFile(filename: "print.i", directory: "/Volumes/Ebi/echeng/radars/r9146594")
 !2 = !{!3}
 !3 = !DIGlobalVariableExpression(var: !4, expr: !DIExpression())
 !4 = !DIGlobalVariable(name: "vsplive", scope: !5, file: !1, line: 617, type: !8, isLocal: true, isDefinition: true)
-!5 = distinct !DISubprogram(name: "drt_vsprintf", scope: !1, file: !1, line: 616, type: !6, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0)
+!5 = distinct !DISubprogram(name: "drt_vsprintf", scope: !1, file: !1, line: 616, type: !6, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
 !6 = !DISubroutineType(types: !7)
 !7 = !{!8}
 !8 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
diff --git a/llvm/test/CodeGen/BPF/BTF/static-var-inited-sec.ll b/llvm/test/CodeGen/BPF/BTF/static-var-inited-sec.ll
index deef48adee9ae..25e62b402dac4 100644
--- a/llvm/test/CodeGen/BPF/BTF/static-var-inited-sec.ll
+++ b/llvm/test/CodeGen/BPF/BTF/static-var-inited-sec.ll
@@ -99,14 +99,14 @@ define dso_local i32 @foo() local_unnamed_addr !dbg !2 {
 
 !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
 !1 = distinct !DIGlobalVariable(name: "b", scope: !2, file: !3, line: 3, type: !14, isLocal: true, isDefinition: true)
-!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !8)
+!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !29)
 !3 = !DIFile(filename: "test.c", directory: "/home/yhs/work/tests/llvm/bug")
 !4 = !DISubroutineType(types: !5)
 !5 = !{!6}
 !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
 !7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !8, globals: !9, nameTableKind: None)
 !8 = !{}
-!9 = !{!0, !10}
+!9 = !{!10}
 !10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression())
 !11 = distinct !DIGlobalVariable(name: "a", scope: !7, file: !3, line: 1, type: !12, isLocal: true, isDefinition: true)
 !12 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !13)
@@ -126,3 +126,4 @@ define dso_local i32 @foo() local_unnamed_addr !dbg !2 {
 !26 = !{!"short", !22, i64 0}
 !27 = !DILocation(line: 4, column: 12, scope: !2)
 !28 = !DILocation(line: 4, column: 3, scope: !2)
+!29 = !{!0}
diff --git a/llvm/test/CodeGen/BPF/BTF/static-var-inited.ll b/llvm/test/CodeGen/BPF/BTF/static-var-inited.ll
index 8f29a83fedb13..9c7e492e170b4 100644
--- a/llvm/test/CodeGen/BPF/BTF/static-var-inited.ll
+++ b/llvm/test/CodeGen/BPF/BTF/static-var-inited.ll
@@ -99,14 +99,14 @@ define dso_local i32 @foo() local_unnamed_addr !dbg !2 {
 
 !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
 !1 = distinct !DIGlobalVariable(name: "b", scope: !2, file: !3, line: 3, type: !14, isLocal: true, isDefinition: true)
-!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !8)
+!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !29)
 !3 = !DIFile(filename: "test.c", directory: "/home/yhs/work/tests/llvm/bug")
 !4 = !DISubroutineType(types: !5)
 !5 = !{!6}
 !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
 !7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !8, globals: !9, nameTableKind: None)
 !8 = !{}
-!9 = !{!0, !10}
+!9 = !{!10}
 !10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression())
 !11 = distinct !DIGlobalVariable(name: "a", scope: !7, file: !3, line: 1, type: !12, isLocal: true, isDefinition: true)
 !12 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !13)
@@ -126,3 +126,4 @@ define dso_local i32 @foo() local_unnamed_addr !dbg !2 {
 !26 = !{!"short", !22, i64 0}
 !27 = !DILocation(line: 4, column: 12, scope: !2)
 !28 = !DILocation(line: 4, column: 3, scope: !2)
+!29 = !{!0}
diff --git a/llvm/test/CodeGen/BPF/BTF/static-var-readonly-sec.ll b/llvm/test/CodeGen/BPF/BTF/static-var-readonly-sec.ll
index e16b4672f53d3..603673eee966e 100644
--- a/llvm/test/CodeGen/BPF/BTF/static-var-readonly-sec.ll
+++ b/llvm/test/CodeGen/BPF/BTF/static-var-readonly-sec.ll
@@ -105,14 +105,14 @@ define dso_local i32 @foo() local_unnamed_addr !dbg !2 {
 
 !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
 !1 = distinct !DIGlobalVariable(name: "b", scope: !2, file: !3, line: 3, type: !15, isLocal: true, isDefinition: true)
-!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !8)
+!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !31)
 !3 = !DIFile(filename: "test.c", directory: "/home/yhs/work/tests/llvm/bug")
 !4 = !DISubroutineType(types: !5)
 !5 = !{!6}
 !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
 !7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !8, globals: !9, nameTableKind: None)
 !8 = !{}
-!9 = !{!0, !10}
+!9 = !{!10}
 !10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression())
 !11 = distinct !DIGlobalVariable(name: "a", scope: !7, file: !3, line: 1, type: !12, isLocal: true, isDefinition: true)
 !12 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !13)
@@ -134,3 +134,4 @@ define dso_local i32 @foo() local_unnamed_addr !dbg !2 {
 !28 = !{!"short", !24, i64 0}
 !29 = !DILocation(line: 4, column: 12, scope: !2)
 !30 = !DILocation(line: 4, column: 3, scope: !2)
+!31 = !{!0}
diff --git a/llvm/test/CodeGen/BPF/BTF/static-var-readonly.ll b/llvm/test/CodeGen/BPF/BTF/static-var-readonly.ll
index 1ddd49904135b..e5df7c1dc8c11 100644
--- a/llvm/test/CodeGen/BPF/BTF/static-var-readonly.ll
+++ b/llvm/test/CodeGen/BPF/BTF/static-var-readonly.ll
@@ -105,14 +105,14 @@ define dso_local i32 @foo() local_unnamed_addr !dbg !2 {
 
 !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
 !1 = distinct !DIGlobalVariable(name: "b", scope: !2, file: !3, line: 3, type: !15, isLocal: true, isDefinition: true)
-!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !8)
+!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !31)
 !3 = !DIFile(filename: "test.c", directory: "/home/yhs/work/tests/llvm/bug")
 !4 = !DISubroutineType(types: !5)
 !5 = !{!6}
 !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
 !7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !8, globals: !9, nameTableKind: None)
 !8 = !{}
-!9 = !{!0, !10}
+!9 = !{!10}
 !10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression())
 !11 = distinct !DIGlobalVariable(name: "a", scope: !7, file: !3, line: 1, type: !12, isLocal: true, isDefinition: true)
 !12 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !13)
@@ -134,3 +134,4 @@ define dso_local i32 @foo() local_unnamed_addr !dbg !2 {
 !28 = !{!"short", !24, i64 0}
 !29 = !DILocation(line: 4, column: 12, scope: !2)
 !30 = !DILocation(line: 4, column: 3, scope: !2)
+!31 = !{!0}
diff --git a/llvm/test/CodeGen/BPF/BTF/static-var-sec.ll b/llvm/test/CodeGen/BPF/BTF/static-var-sec.ll
index 0ff8f2eb7db84..0168d30fffc2a 100644
--- a/llvm/test/CodeGen/BPF/BTF/static-var-sec.ll
+++ b/llvm/test/CodeGen/BPF/BTF/static-var-sec.ll
@@ -99,14 +99,14 @@ define dso_local i32 @foo() local_unnamed_addr !dbg !2 {
 
 !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
 !1 = distinct !DIGlobalVariable(name: "b", scope: !2, file: !3, line: 3, type: !14, isLocal: true, isDefinition: true)
-!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !8)
+!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !29)
 !3 = !DIFile(filename: "test.c", directory: "/home/yhs/work/tests/llvm/bug")
 !4 = !DISubroutineType(types: !5)
 !5 = !{!6}
 !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
 !7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !8, globals: !9, nameTableKind: None)
 !8 = !{}
-!9 = !{!0, !10}
+!9 = !{!10}
 !10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression())
 !11 = distinct !DIGlobalVariable(name: "a", scope: !7, file: !3, line: 1, type: !12, isLocal: true, isDefinition: true)
 !12 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !13)
@@ -126,3 +126,4 @@ define dso_local i32 @foo() local_unnamed_addr !dbg !2 {
 !26 = !{!"short", !22, i64 0}
 !27 = !DILocation(line: 4, column: 12, scope: !2)
 !28 = !DILocation(line: 4, column: 3, scope: !2)
+!29 = !{!0}
diff --git a/llvm/test/CodeGen/BPF/BTF/static-var.ll b/llvm/test/CodeGen/BPF/BTF/static-var.ll
index f7710e3f3ce45..43781e4d91183 100644
--- a/llvm/test/CodeGen/BPF/BTF/static-var.ll
+++ b/llvm/test/CodeGen/BPF/BTF/static-var.ll
@@ -99,14 +99,14 @@ define dso_local i32 @foo() local_unnamed_addr !dbg !2 {
 
 !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
 !1 = distinct !DIGlobalVariable(name: "b", scope: !2, file: !3, line: 3, type: !14, isLocal: true, isDefinition: true)
-!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !8)
+!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !29)
 !3 = !DIFile(filename: "test.c", directory: "/home/yhs/work/tests/llvm/bug")
 !4 = !DISubroutineType(types: !5)
 !5 = !{!6}
 !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
 !7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !8, globals: !9, nameTableKind: None)
 !8 = !{}
-!9 = !{!0, !10}
+!9 = !{!10}
 !10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression())
 !11 = distinct !DIGlobalVariable(name: "a", scope: !7, file: !3, line: 1, type: !12, isLocal: true, isDefinition: true)
 !12 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !13)
@@ -126,3 +126,4 @@ define dso_local i32 @foo() local_unnamed_addr !dbg !2 {
 !26 = !{!"short", !22, i64 0}
 !27 = !DILocation(line: 4, column: 12, scope: !2)
 !28 = !DILocation(line: 4, column: 3, scope: !2)
+!29 = !{!0}
diff --git a/llvm/test/CodeGen/BPF/dwarfdump.ll b/llvm/test/CodeGen/BPF/dwarfdump.ll
index d50c025c4e6f8..68b0779450eac 100644
--- a/llvm/test/CodeGen/BPF/dwarfdump.ll
+++ b/llvm/test/CodeGen/BPF/dwarfdump.ll
@@ -34,10 +34,9 @@ declare void @llvm.dbg.value(metadata, i64, metadata, metadata)
 !4 = !DISubroutineType(types: !5)
 !5 = !{!6, !6, !6}
 !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 4.0.0 (trunk 287518) (llvm/trunk 287520)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !8, globals: !9)
+!7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 4.0.0 (trunk 287518) (llvm/trunk 287520)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !8)
 !8 = !{}
-!9 = !{!0}
-!10 = !{!11, !12}
+!10 = !{!0, !11, !12}
 !11 = !DILocalVariable(name: "myvar_a", arg: 1, scope: !2, file: !3, line: 1, type: !6)
 !12 = !DILocalVariable(name: "myvar_b", arg: 2, scope: !2, file: !3, line: 1, type: !6)
 !13 = !{i32 2, !"Dwarf Version", i32 4}
diff --git a/llvm/test/CodeGen/PowerPC/pr24546.ll b/llvm/test/CodeGen/PowerPC/pr24546.ll
index a84b2e894f111..e4ff2ff9fe8a8 100644
--- a/llvm/test/CodeGen/PowerPC/pr24546.ll
+++ b/llvm/test/CodeGen/PowerPC/pr24546.ll
@@ -56,7 +56,7 @@ attributes #3 = { nounwind }
 !llvm.module.flags = !{!29, !30}
 !llvm.ident = !{!31}
 
-!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.8.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, globals: !23)
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.8.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3)
 !1 = !DIFile(filename: "testcase.i", directory: "/tmp/glibc.build")
 !2 = !{}
 !3 = !{!4}
@@ -76,9 +76,8 @@ attributes #3 = { nounwind }
 !18 = distinct !DISubprogram(name: "php_intpow10", scope: !1, file: !1, line: 1, type: !19, isLocal: true, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !21)
 !19 = !DISubroutineType(types: !20)
 !20 = !{!4, !9}
-!21 = !{!22}
+!21 = !{!22, !24}
 !22 = !DILocalVariable(name: "power", arg: 1, scope: !18, file: !1, line: 1, type: !9)
-!23 = !{!24}
 !24 = !DIGlobalVariableExpression(var: !DIGlobalVariable(name: "powers", scope: !18, file: !1, line: 3, type: !25, isLocal: true, isDefinition: true), expr: !DIExpression())
 !25 = !DICompositeType(tag: DW_TAG_array_type, baseType: !26, size: 1472, align: 64, elements: !27)
 !26 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !4)
diff --git a/llvm/test/CodeGen/X86/dbg-distringtype-uint.ll b/llvm/test/CodeGen/X86/dbg-distringtype-uint.ll
index 47b32967e68f7..f229ab1a6e34f 100644
--- a/llvm/test/CodeGen/X86/dbg-distringtype-uint.ll
+++ b/llvm/test/CodeGen/X86/dbg-distringtype-uint.ll
@@ -84,10 +84,9 @@ attributes #3 = { nofree nosync nounwind readnone speculatable willreturn }
 !5 = !DISubroutineType(types: !6)
 !6 = !{!7}
 !7 = !DIStringType(name: "CHARACTER_0", size: 64)
-!8 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 21.0-2745", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !9, globals: !10, splitDebugInlining: false, nameTableKind: None)
+!8 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 21.0-2745", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !9, splitDebugInlining: false, nameTableKind: None)
 !9 = !{}
-!10 = !{!0}
-!11 = !{!12, !14}
+!11 = !{!0, !12, !14}
 !12 = !DILocalVariable(name: "esym", arg: 1, scope: !2, file: !3, line: 15, type: !13, flags: DIFlagArtificial)
 !13 = !DIStringType(name: "CHARACTER_1", size: 64)
 !14 = !DILocalVariable(name: "i", arg: 2, scope: !2, file: !3, line: 15, type: !15)
diff --git a/llvm/test/DebugInfo/COFF/fortran-basic.ll b/llvm/test/DebugInfo/COFF/fortran-basic.ll
index 1a44235553820..bf58b062a9755 100644
--- a/llvm/test/DebugInfo/COFF/fortran-basic.ll
+++ b/llvm/test/DebugInfo/COFF/fortran-basic.ll
@@ -149,7 +149,7 @@ attributes #3 = { nocallback nofree nosync nounwind readnone speculatable willre
 !5 = !DISubroutineType(types: !6)
 !6 = !{null}
 !7 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !4, producer: "Fortran", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !8, splitDebugInlining: false, nameTableKind: None)
-!8 = !{!0, !9, !12, !15, !21}
+!8 = !{!0, !9, !12}
 !9 = !DIGlobalVariableExpression(var: !10, expr: !DIExpression(DW_OP_plus_uconst, 8))
 !10 = distinct !DIGlobalVariable(name: "L", linkageName: "COM", scope: !2, file: !4, line: 6, type: !11, isLocal: false, isDefinition: true)
 !11 = !DIBasicType(name: "LOGICAL*4", size: 32, encoding: DW_ATE_boolean)
@@ -167,7 +167,7 @@ attributes #3 = { nocallback nofree nosync nounwind readnone speculatable willre
 !23 = !DICompositeType(tag: DW_TAG_array_type, baseType: !18, elements: !24)
 !24 = !{!25}
 !25 = !DISubrange(count: 10, lowerBound: 1)
-!26 = !{!27, !29, !31}
+!26 = !{!15, !21, !27, !29, !31}
 !27 = !DILocalVariable(name: "CMP32", scope: !3, file: !4, line: 10, type: !28)
 !28 = !DIBasicType(name: "COMPLEX*32", size: 256, encoding: DW_ATE_complex_float)
 !29 = !DILocalVariable(name: "CMP16", scope: !3, file: !4, line: 9, type: !30)
diff --git a/llvm/test/DebugInfo/COFF/fortran-contained-proc.ll b/llvm/test/DebugInfo/COFF/fortran-contained-proc.ll
index 9d79d913ba57b..a9371cd7b0886 100644
--- a/llvm/test/DebugInfo/COFF/fortran-contained-proc.ll
+++ b/llvm/test/DebugInfo/COFF/fortran-contained-proc.ll
@@ -86,11 +86,11 @@ attributes #4 = { nounwind }
 
 !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
 !1 = distinct !DIGlobalVariable(name: "A", linkageName: "IF_TEST$A", scope: !2, file: !3, line: 11, type: !9, isLocal: true, isDefinition: true)
-!2 = distinct !DISubprogram(name: "IF_TEST", linkageName: "MAIN__", scope: !3, file: !3, line: 9, type: !4, scopeLine: 9, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !6, retainedNodes: !8)
+!2 = distinct !DISubprogram(name: "IF_TEST", linkageName: "MAIN__", scope: !3, file: !3, line: 9, type: !4, scopeLine: 9, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !6, retainedNodes: !7)
 !3 = !DIFile(filename: "tr1.f90", directory: "d:\\iusers\\cchen15\\examples\\tests\\jr14335")
 !4 = !DISubroutineType(types: !5)
 !5 = !{null}
-!6 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 22.0-1087", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !7, splitDebugInlining: false, nameTableKind: None)
+!6 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 22.0-1087", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !8, splitDebugInlining: false, nameTableKind: None)
 !7 = !{!0}
 !8 = !{}
 !9 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64)
diff --git a/llvm/test/DebugInfo/COFF/global_visibility.ll b/llvm/test/DebugInfo/COFF/global_visibility.ll
index 499690a854eeb..12ff172fb5a02 100644
--- a/llvm/test/DebugInfo/COFF/global_visibility.ll
+++ b/llvm/test/DebugInfo/COFF/global_visibility.ll
@@ -208,10 +208,10 @@ attributes #2 = { nounwind readnone speculatable willreturn }
 !2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 11.0.0 (https://github.com/llvm/llvm-project.git 202f144bffd0be254a829924195e1b8ebabcbb79)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None)
 !3 = !DIFile(filename: "a.cpp", directory: "F:\\llvm-project\\__test", checksumkind: CSK_MD5, checksum: "66a5399777dc9d37656fb00438bca542")
 !4 = !{}
-!5 = !{!0, !6, !12, !14, !17, !19, !29}
+!5 = !{!0, !19, !29}
 !6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression())
 !7 = distinct !DIGlobalVariable(name: "local_int", scope: !8, file: !3, line: 15, type: !11, isLocal: true, isDefinition: true)
-!8 = distinct !DISubprogram(name: "foo", linkageName: "?foo@@YAXXZ", scope: !3, file: !3, line: 14, type: !9, scopeLine: 14, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !4)
+!8 = distinct !DISubprogram(name: "foo", linkageName: "?foo@@YAXXZ", scope: !3, file: !3, line: 14, type: !9, scopeLine: 14, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !67)
 !9 = !DISubroutineType(types: !10)
 !10 = !{null}
 !11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
@@ -219,7 +219,7 @@ attributes #2 = { nounwind readnone speculatable willreturn }
 !13 = distinct !DIGlobalVariable(name: "nested_int", scope: !8, file: !3, line: 17, type: !11, isLocal: true, isDefinition: true)
 !14 = !DIGlobalVariableExpression(var: !15, expr: !DIExpression())
 !15 = distinct !DIGlobalVariable(name: "local_int", scope: !16, file: !3, line: 24, type: !11, isLocal: true, isDefinition: true)
-!16 = distinct !DISubprogram(name: "bar", linkageName: "?bar@@YAXXZ", scope: !3, file: !3, line: 23, type: !9, scopeLine: 23, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !4)
+!16 = distinct !DISubprogram(name: "bar", linkageName: "?bar@@YAXXZ", scope: !3, file: !3, line: 23, type: !9, scopeLine: 23, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !68)
 !17 = !DIGlobalVariableExpression(var: !18, expr: !DIExpression())
 !18 = distinct !DIGlobalVariable(name: "nested_int", scope: !16, file: !3, line: 26, type: !11, isLocal: true, isDefinition: true)
 !19 = !DIGlobalVariableExpression(var: !20, expr: !DIExpression())
@@ -270,3 +270,5 @@ attributes #2 = { nounwind readnone speculatable willreturn }
 !64 = !DILocation(line: 6, scope: !60)
 !65 = !DILocation(line: 7, scope: !60)
 !66 = !DILocation(line: 8, scope: !60)
+!67 = !{!6, !12}
+!68 = !{!14, !17}
diff --git a/llvm/test/DebugInfo/COFF/type-quals.ll b/llvm/test/DebugInfo/COFF/type-quals.ll
index bca2590ea7969..fd71796ed567c 100644
--- a/llvm/test/DebugInfo/COFF/type-quals.ll
+++ b/llvm/test/DebugInfo/COFF/type-quals.ll
@@ -487,14 +487,14 @@ attributes #2 = { argmemonly nounwind }
 
 !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
 !1 = distinct !DIGlobalVariable(name: "str", scope: !2, file: !3, line: 18, type: !12, isLocal: true, isDefinition: true)
-!2 = distinct !DISubprogram(name: "g", linkageName: "\01?g@@YAXAEIAH at Z", scope: !3, file: !3, line: 16, type: !4, isLocal: false, isDefinition: true, scopeLine: 16, flags: DIFlagPrototyped, isOptimized: false, unit: !9, retainedNodes: !10)
+!2 = distinct !DISubprogram(name: "g", linkageName: "\01?g@@YAXAEIAH at Z", scope: !3, file: !3, line: 16, type: !4, isLocal: false, isDefinition: true, scopeLine: 16, flags: DIFlagPrototyped, isOptimized: false, unit: !9, retainedNodes: !11)
 !3 = !DIFile(filename: "m.cpp", directory: "C:\5CUsers\5CHui\5Ctmp\5Chui", checksumkind: CSK_MD5, checksum: "a8da0f4dca948db1ef1129c8728a881c")
 !4 = !DISubroutineType(types: !5)
 !5 = !{null, !6}
 !6 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !7)
 !7 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !8, size: 64)
 !8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!9 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 7.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !10, globals: !11)
+!9 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 7.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !10, globals: !10)
 !10 = !{}
 !11 = !{!0}
 !12 = !DICompositeType(tag: DW_TAG_array_type, baseType: !13, size: 32, elements: !15)
diff --git a/llvm/test/DebugInfo/Generic/2009-11-05-DeadGlobalVariable.ll b/llvm/test/DebugInfo/Generic/2009-11-05-DeadGlobalVariable.ll
index c26cba6be3b30..dd107d1adc627 100644
--- a/llvm/test/DebugInfo/Generic/2009-11-05-DeadGlobalVariable.ll
+++ b/llvm/test/DebugInfo/Generic/2009-11-05-DeadGlobalVariable.ll
@@ -14,13 +14,13 @@ attributes #0 = { nounwind readnone ssp uwtable }
 !llvm.dbg.cu = !{!0}
 !llvm.module.flags = !{!10}
 
-!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.0 (trunk 139632)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !3)
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.0 (trunk 139632)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2)
 !1 = !DIFile(filename: "fb.c", directory: "/private/tmp")
 !2 = !{}
 !3 = !{!4}
 !4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression())
 !5 = !DIGlobalVariable(name: "bar", scope: !6, file: !1, line: 2, type: !9, isLocal: true, isDefinition: true)
-!6 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: true, unit: !0)
+!6 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: true, unit: !0, retainedNodes: !3)
 !7 = !DISubroutineType(types: !8)
 !8 = !{!9}
 !9 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
diff --git a/llvm/test/DebugInfo/Generic/inlined-static-var.ll b/llvm/test/DebugInfo/Generic/inlined-static-var.ll
index 60c986fc2b648..99bca52c975dc 100644
--- a/llvm/test/DebugInfo/Generic/inlined-static-var.ll
+++ b/llvm/test/DebugInfo/Generic/inlined-static-var.ll
@@ -59,17 +59,17 @@ define dso_local i32 @_Z3foov() !dbg !26 {
 
 !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
 !1 = distinct !DIGlobalVariable(name: "B", scope: !2, file: !3, line: 5, type: !6, isLocal: true, isDefinition: true)
-!2 = distinct !DISubprogram(name: "not_removed", linkageName: "_Z11not_removedv", scope: !3, file: !3, line: 5, type: !4, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !13)
+!2 = distinct !DISubprogram(name: "not_removed", linkageName: "_Z11not_removedv", scope: !3, file: !3, line: 5, type: !4, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !9)
 !3 = !DIFile(filename: "example.cpp", directory: "")
 !4 = !DISubroutineType(types: !5)
 !5 = !{!6}
 !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!7 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !8, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !9, splitDebugInlining: false, nameTableKind: None)
+!7 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !8, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
 !8 = !DIFile(filename: "example.cpp", directory: "")
-!9 = !{!0, !10}
+!9 = !{!0}
 !10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression())
 !11 = distinct !DIGlobalVariable(name: "A", scope: !12, file: !3, line: 2, type: !6, isLocal: false, isDefinition: true)
-!12 = distinct !DISubprogram(name: "removed", linkageName: "_Z7removedv", scope: !3, file: !3, line: 2, type: !4, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !13)
+!12 = distinct !DISubprogram(name: "removed", linkageName: "_Z7removedv", scope: !3, file: !3, line: 2, type: !4, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !33)
 !13 = !{}
 !14 = !{i32 7, !"Dwarf Version", i32 4}
 !15 = !{i32 2, !"Debug Info Version", i32 3}
@@ -90,3 +90,4 @@ define dso_local i32 @_Z3foov() !dbg !26 {
 !30 = distinct !DILocation(line: 7, column: 32, scope: !26)
 !31 = !DILocation(line: 7, column: 30, scope: !26)
 !32 = !DILocation(line: 7, column: 13, scope: !26)
+!33 = !{!10}
diff --git a/llvm/test/DebugInfo/Generic/verifier-invalid-dicompileunit.ll b/llvm/test/DebugInfo/Generic/verifier-invalid-dicompileunit.ll
new file mode 100644
index 0000000000000..fd4a366cb64c8
--- /dev/null
+++ b/llvm/test/DebugInfo/Generic/verifier-invalid-dicompileunit.ll
@@ -0,0 +1,62 @@
+; RUN: llvm-as -disable-output %s 2>&1 | FileCheck --match-full-lines %s
+
+!llvm.module.flags = !{!0}
+!llvm.dbg.cu = !{!2, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !17, !20, !22}
+
+!0 = !{i32 2, !"Debug Info Version", i32 3}
+!1 = !DIFile(filename: "-", directory: "")
+
+; CHECK: invalid file
+!2 = distinct !DICompileUnit(language: 0, file: !{})
+
+; CHECK: invalid filename
+!3 = !DIFile(filename: "", directory: "")
+!4 = distinct !DICompileUnit(language: 0, file: !3)
+
+; CHECK: invalid enum list
+!5 = distinct !DICompileUnit(language: 0, file: !1, enums: !1)
+
+; CHECK: invalid enum type
+!6 = distinct !DICompileUnit(language: 0, file: !1, enums: !{!1})
+
+; CHECK: invalid retained type list
+!7 = distinct !DICompileUnit(language: 0, file: !1, retainedTypes: !1)
+
+; CHECK: invalid retained type
+!8 = distinct !DICompileUnit(language: 0, file: !1, retainedTypes: !{!1})
+
+; CHECK: invalid global variable list
+!9 = distinct !DICompileUnit(language: 0, file: !1, globals: !1)
+
+; CHECK: invalid global variable ref
+!10 = distinct !DICompileUnit(language: 0, file: !1, globals: !{!1})
+
+; CHECK: invalid imported entity list
+!11 = distinct !DICompileUnit(language: 0, file: !1, imports: !1)
+
+; CHECK: invalid imported entity ref
+!12 = distinct !DICompileUnit(language: 0, file: !1, imports: !{!1})
+
+; CHECK: invalid macro list
+!13 = distinct !DICompileUnit(language: 0, file: !1, macros: !1)
+
+; CHECK: invalid macro ref
+!14 = distinct !DICompileUnit(language: 0, file: !1, macros: !{!1})
+
+define void @foo() !dbg !15 { ret void }
+!15 = distinct !DISubprogram(file: !1)
+
+; CHECK: function-local imports are not allowed in a DICompileUnit's imported entities list
+!16 = distinct !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !15, entity: !15)
+!17 = distinct !DICompileUnit(language: 0, file: !1, imports: !{!16})
+
+; CHECK: function-local variables are not allowed in a DICompileUnit's global variables list
+!18 = !DIGlobalVariableExpression(var: !19, expr: !DIExpression())
+!19 = distinct !DIGlobalVariable(scope: !15)
+!20 = distinct !DICompileUnit(language: 0, file: !1, globals: !{!18})
+
+; CHECK: function-local enum in a DICompileUnit's enum list
+!21 = distinct !DICompositeType(tag: DW_TAG_enumeration_type, scope: !15)
+!22 = distinct !DICompileUnit(language: 0, file: !1, enums: !{!21})
+
+; CHECK: warning: ignoring invalid debug info{{.*}}
diff --git a/llvm/test/DebugInfo/Generic/verifier-invalid-disubprogram.ll b/llvm/test/DebugInfo/Generic/verifier-invalid-disubprogram.ll
index 54ce1c56c6b30..52b087e540108 100644
--- a/llvm/test/DebugInfo/Generic/verifier-invalid-disubprogram.ll
+++ b/llvm/test/DebugInfo/Generic/verifier-invalid-disubprogram.ll
@@ -38,7 +38,7 @@ define void @invalid_subprogram_declaration() !dbg !9 { ret void }
 define void @invalid_retained_nodes_list() !dbg !10 { ret void }
 !10 = distinct !DISubprogram(retainedNodes: !0)
 
-; CHECK: invalid retained nodes, expected DILocalVariable, DILabel, DIImportedEntity or DIType
+; CHECK: invalid retained nodes, expected DILocalVariable, DILabel, DIImportedEntity, DIType or DIGlobalVariableExpression
 define void @invalid_retained_nodes_expected() !dbg !11 { ret void }
 !11 = distinct !DISubprogram(retainedNodes: !{!0})
 
diff --git a/llvm/test/DebugInfo/Symbolize/XCOFF/xcoff-symbolize-data.ll b/llvm/test/DebugInfo/Symbolize/XCOFF/xcoff-symbolize-data.ll
index 1a467ec72a75d..3a8ee66e9b797 100644
--- a/llvm/test/DebugInfo/Symbolize/XCOFF/xcoff-symbolize-data.ll
+++ b/llvm/test/DebugInfo/Symbolize/XCOFF/xcoff-symbolize-data.ll
@@ -116,7 +116,7 @@ attributes #2 = { nocallback nofree nosync nounwind speculatable willreturn memo
 !1 = distinct !DIGlobalVariable(name: "bss_global", scope: !2, file: !3, line: 1, type: !7, isLocal: false, isDefinition: true)
 !2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 18.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None)
 !3 = !DIFile(filename: "t.cpp", directory: "/")
-!4 = !{!0, !5, !8, !15, !18, !24, !26}
+!4 = !{!0, !5, !8, !15, !24, !26}
 !5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression())
 !6 = distinct !DIGlobalVariable(name: "data_global", scope: !2, file: !3, line: 2, type: !7, isLocal: false, isDefinition: true)
 !7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
@@ -132,7 +132,7 @@ attributes #2 = { nocallback nofree nosync nounwind speculatable willreturn memo
 !17 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 32)
 !18 = !DIGlobalVariableExpression(var: !19, expr: !DIExpression())
 !19 = distinct !DIGlobalVariable(name: "function_global", scope: !20, file: !3, line: 8, type: !7, isLocal: true, isDefinition: true)
-!20 = distinct !DISubprogram(name: "f", linkageName: "_Z1fv", scope: !3, file: !3, line: 7, type: !21, scopeLine: 7, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2)
+!20 = distinct !DISubprogram(name: "f", linkageName: "_Z1fv", scope: !3, file: !3, line: 7, type: !21, scopeLine: 7, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !47)
 !21 = !DISubroutineType(types: !22)
 !22 = !{!23}
 !23 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 32)
@@ -159,3 +159,4 @@ attributes #2 = { nocallback nofree nosync nounwind speculatable willreturn memo
 !44 = !{!"int", !45, i64 0}
 !45 = !{!"omnipotent char", !46, i64 0}
 !46 = !{!"Simple C++ TBAA"}
+!47 = !{!18}
diff --git a/llvm/test/DebugInfo/X86/DW_AT_specification.ll b/llvm/test/DebugInfo/X86/DW_AT_specification.ll
index 826ec11782032..a8d01bb715c6d 100644
--- a/llvm/test/DebugInfo/X86/DW_AT_specification.ll
+++ b/llvm/test/DebugInfo/X86/DW_AT_specification.ll
@@ -23,13 +23,13 @@ entry:
 
 !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
 !1 = !DIGlobalVariable(name: "x", scope: !2, file: !3, line: 5, type: !14, isLocal: true, isDefinition: true)
-!2 = distinct !DISubprogram(name: "bar", linkageName: "_ZN3foo3barEv", scope: null, file: !3, line: 4, type: !4, isLocal: false, isDefinition: true, scopeLine: 4, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !8, declaration: !11)
+!2 = distinct !DISubprogram(name: "bar", linkageName: "_ZN3foo3barEv", scope: null, file: !3, line: 4, type: !4, isLocal: false, isDefinition: true, scopeLine: 4, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !8, declaration: !11, retainedNodes: !10)
 !3 = !DIFile(filename: "nsNativeAppSupportBase.ii", directory: "/Users/espindola/mozilla-central/obj-x86_64-apple-darwin11.2.0/toolkit/library")
 !4 = !DISubroutineType(types: !5)
 !5 = !{null, !6}
 !6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64, align: 64, flags: DIFlagArtificial)
 !7 = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", file: !3, line: 1, flags: DIFlagFwdDecl)
-!8 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 3.0 ()", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !9, retainedTypes: !9, globals: !10, imports: !9)
+!8 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 3.0 ()", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !9, retainedTypes: !9, imports: !9)
 !9 = !{}
 !10 = !{!0}
 !11 = !DISubprogram(name: "bar", linkageName: "_ZN3foo3barEv", scope: !12, file: !3, line: 2, type: !4, isLocal: false, isDefinition: false, scopeLine: 2, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false)
diff --git a/llvm/test/DebugInfo/X86/dbg-value-transfer-order.ll b/llvm/test/DebugInfo/X86/dbg-value-transfer-order.ll
index 1261bc3a1cf6f..56e6be7489e48 100644
--- a/llvm/test/DebugInfo/X86/dbg-value-transfer-order.ll
+++ b/llvm/test/DebugInfo/X86/dbg-value-transfer-order.ll
@@ -97,13 +97,13 @@ attributes #1 = { nounwind readnone speculatable }
 !llvm.module.flags = !{!14, !15, !16, !17}
 !llvm.ident = !{!18}
 
-!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3)
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !2)
 !1 = !DIFile(filename: "t.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild", checksumkind: CSK_MD5, checksum: "f80d0003faf76554dfdec6c95da285cc")
 !2 = !{}
 !3 = !{!4}
 !4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression())
 !5 = distinct !DIGlobalVariable(name: "pages", scope: !6, file: !1, line: 18, type: !10, isLocal: true, isDefinition: true)
-!6 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 17, type: !7, isLocal: false, isDefinition: true, scopeLine: 17, isOptimized: true, unit: !0, retainedNodes: !2)
+!6 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 17, type: !7, isLocal: false, isDefinition: true, scopeLine: 17, isOptimized: true, unit: !0, retainedNodes: !3)
 !7 = !DISubroutineType(types: !8)
 !8 = !{!9}
 !9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
diff --git a/llvm/test/DebugInfo/X86/dimodule-external-fortran.ll b/llvm/test/DebugInfo/X86/dimodule-external-fortran.ll
index 60010c50a8f12..c8e1cb29e5df9 100644
--- a/llvm/test/DebugInfo/X86/dimodule-external-fortran.ll
+++ b/llvm/test/DebugInfo/X86/dimodule-external-fortran.ll
@@ -73,13 +73,12 @@ attributes #1 = { nofree nosync nounwind readnone speculatable willreturn }
 !3 = !DIFile(filename: "em.f90", directory: "tests")
 !4 = !DISubroutineType(types: !5)
 !5 = !{null}
-!6 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 21.0-2165", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !7, globals: !8, splitDebugInlining: false, nameTableKind: None)
+!6 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 21.0-2165", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !7, splitDebugInlining: false, nameTableKind: None)
 !7 = !{}
-!8 = !{!0}
 !9 = !{}
 !10 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !2, entity: !11, file: !3, line: 2)
 !11 = !DIModule(scope: !2, name: "external_module", isDecl: true)
-!12 = !{!10, !13}
+!12 = !{!0, !10, !13}
 !13 = !DILocalVariable(name: "x", scope: !2, file: !3, line: 5, type: !14)
 !14 = !DIBasicType(name: "REAL*4", size: 32, encoding: DW_ATE_float)
 !15 = !{i32 2, !"Debug Info Version", i32 3}
diff --git a/llvm/test/DebugInfo/X86/distringtype.ll b/llvm/test/DebugInfo/X86/distringtype.ll
index 80ec7d628a0ee..2930c3aed0485 100644
--- a/llvm/test/DebugInfo/X86/distringtype.ll
+++ b/llvm/test/DebugInfo/X86/distringtype.ll
@@ -145,11 +145,11 @@ attributes #1 = { nofree nosync nounwind readnone speculatable willreturn }
 
 !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
 !1 = distinct !DIGlobalVariable(name: "deferred", linkageName: "assumedlength_$DEFERRED", scope: !2, file: !3, line: 2, type: !9, isLocal: true, isDefinition: true)
-!2 = distinct !DISubprogram(name: "assumedlength", linkageName: "MAIN__", scope: !3, file: !3, line: 1, type: !4, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !7)
+!2 = distinct !DISubprogram(name: "assumedlength", linkageName: "MAIN__", scope: !3, file: !3, line: 1, type: !4, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !8)
 !3 = !DIFile(filename: "distring.f90", directory: "/iusers/cchen15/examples/tests")
 !4 = !DISubroutineType(types: !5)
 !5 = !{null}
-!6 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 21.0-2142", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !7, globals: !8, splitDebugInlining: false, nameTableKind: None)
+!6 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 21.0-2142", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !7, splitDebugInlining: false, nameTableKind: None)
 !7 = !{}
 !8 = !{!0}
 !9 = !DIStringType(name: ".str.DEFERRED", stringLengthExpression: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8), stringLocationExpression: !DIExpression(DW_OP_push_object_address, DW_OP_deref))
diff --git a/llvm/test/DebugInfo/X86/global-sra-struct-fit-segment.ll b/llvm/test/DebugInfo/X86/global-sra-struct-fit-segment.ll
index ab48ef2411f35..f1d619e7cb187 100644
--- a/llvm/test/DebugInfo/X86/global-sra-struct-fit-segment.ll
+++ b/llvm/test/DebugInfo/X86/global-sra-struct-fit-segment.ll
@@ -90,9 +90,9 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata)
 
 !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
 !1 = distinct !DIGlobalVariable(name: "nodea", scope: !2, file: !3, line: 3, type: !9, isLocal: true, isDefinition: true)
-!2 = distinct !DISubprogram(name: "sub", scope: !4, file: !3, line: 1, type: !12, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition, unit: !4)
+!2 = distinct !DISubprogram(name: "sub", scope: !4, file: !3, line: 1, type: !12, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition, unit: !4, retainedNodes: !6)
 !3 = !DIFile(filename: "global-sra-struct-fit-segment.f90", directory: "/tmp")
-!4 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, flags: "'+flang -g -O0 -S -emit-llvm'", runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !5, nameTableKind: None)
+!4 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, flags: "'+flang -g -O0 -S -emit-llvm'", runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !5, imports: !5, nameTableKind: None)
 !5 = !{}
 !6 = !{!0, !7, !10, !29}
 !7 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression(DW_OP_plus_uconst, 4))
diff --git a/llvm/test/DebugInfo/X86/global-sra-struct-part-overlap-segment.ll b/llvm/test/DebugInfo/X86/global-sra-struct-part-overlap-segment.ll
index 9dd865edbbdad..3dd4d9c6cca7f 100644
--- a/llvm/test/DebugInfo/X86/global-sra-struct-part-overlap-segment.ll
+++ b/llvm/test/DebugInfo/X86/global-sra-struct-part-overlap-segment.ll
@@ -171,10 +171,10 @@ declare void @llvm.experimental.noalias.scope.decl(metadata)
 !3 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !4, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: true, flags: "'+flang -g -O3 -S -emit-llvm -o -O1'", runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !5, nameTableKind: None)
 !4 = !DIFile(filename: "global-sra-struct-part-overlap-segment_0.f90", directory: "/tmp")
 !5 = !{}
-!6 = !{!0, !7, !29}
+!6 = !{!0}
 !7 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression())
 !8 = distinct !DIGlobalVariable(name: "rvar", scope: !9, file: !4, line: 13, type: !19, isLocal: true, isDefinition: true)
-!9 = distinct !DISubprogram(name: "bar", scope: !2, file: !4, line: 10, type: !10, scopeLine: 10, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !3)
+!9 = distinct !DISubprogram(name: "bar", scope: !2, file: !4, line: 10, type: !10, scopeLine: 10, retainedNodes: !32, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !3)
 !10 = !DISubroutineType(types: !11)
 !11 = !{null, !12, !16}
 !12 = !DICompositeType(tag: DW_TAG_array_type, baseType: !13, size: 96, align: 32, elements: !14)
@@ -197,3 +197,4 @@ declare void @llvm.experimental.noalias.scope.decl(metadata)
 !29 = !DIGlobalVariableExpression(var: !30, expr: !DIExpression(DW_OP_plus_uconst, 4))
 !30 = distinct !DIGlobalVariable(name: "ivar", scope: !9, file: !4, line: 13, type: !31, isLocal: true, isDefinition: true)
 !31 = !DIBasicType(name: "integer*8", size: 64, align: 32, encoding: DW_ATE_signed)
+!32 = !{!7, !29}
diff --git a/llvm/test/DebugInfo/X86/gnu-public-names.ll b/llvm/test/DebugInfo/X86/gnu-public-names.ll
index 5d81468f55379..1c3ac763c6dc6 100644
--- a/llvm/test/DebugInfo/X86/gnu-public-names.ll
+++ b/llvm/test/DebugInfo/X86/gnu-public-names.ll
@@ -332,7 +332,7 @@ attributes #1 = { nounwind readnone speculatable }
 !14 = !{!15}
 !15 = !DIEnumerator(name: "named_enum_class_enumerator", value: 0)
 !16 = !{!13}
-!17 = !{!0, !18, !29, !32, !37, !44, !47, !50}
+!17 = !{!0, !18, !29, !32, !44, !47, !50}
 !18 = !DIGlobalVariableExpression(var: !19, expr: !DIExpression())
 !19 = distinct !DIGlobalVariable(name: "global_variable", scope: !2, file: !3, line: 13, type: !20, isLocal: false, isDefinition: true)
 !20 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "C", file: !3, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !21, identifier: "_ZTS1C")
@@ -354,7 +354,7 @@ attributes #1 = { nounwind readnone speculatable }
 !36 = !DIDerivedType(tag: DW_TAG_member, name: "A", scope: !34, file: !3, line: 22, baseType: !13, size: 32)
 !37 = !DIGlobalVariableExpression(var: !38, expr: !DIExpression())
 !38 = distinct !DIGlobalVariable(name: "z", scope: !39, file: !3, line: 33, type: !13, isLocal: true, isDefinition: true)
-!39 = distinct !DISubprogram(name: "f3", linkageName: "_Z2f3v", scope: !3, file: !3, line: 32, type: !40, scopeLine: 32, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !43)
+!39 = distinct !DISubprogram(name: "f3", linkageName: "_Z2f3v", scope: !3, file: !3, line: 32, type: !40, scopeLine: 32, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !91)
 !40 = !DISubroutineType(types: !41)
 !41 = !{!42}
 !42 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64)
@@ -406,3 +406,4 @@ attributes #1 = { nounwind readnone speculatable }
 !88 = !DILocation(line: 59, column: 68, scope: !78)
 !89 = !DILocation(line: 60, column: 32, scope: !78)
 !90 = !DILocation(line: 59, column: 3, scope: !78)
+!91 = !{!37}
diff --git a/llvm/test/DebugInfo/X86/lexical-block-static-var.ll b/llvm/test/DebugInfo/X86/lexical-block-static-var.ll
new file mode 100644
index 0000000000000..2c90ac02d4306
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/lexical-block-static-var.ll
@@ -0,0 +1,145 @@
+; RUN: %llc_dwarf -O0 -filetype=obj < %s | llvm-dwarfdump -debug-info - | FileCheck --implicit-check-not "{{DW_TAG|NULL}}" %s
+
+; inline __attribute__((always_inline))
+; int removed() {
+;   {
+;     static int A;
+;     return A++;
+;   }
+; }
+;
+; __attribute__((always_inline))
+; int not_removed() {
+;   {
+;     static int B;
+;     return B++;
+;   }
+; }
+;
+; int foo() {
+;   {
+;     static int C;
+;     return ++C + removed() + not_removed();
+;   }
+; }
+
+; CHECK: DW_TAG_compile_unit
+
+; Out-of-line definition of `not_removed()`.
+; The empty lexical block is created to match abstract origin.
+; CHECK:   DW_TAG_subprogram
+; CHECK:     DW_AT_abstract_origin {{.*}} "_Z11not_removedv"
+; CHECK:     DW_TAG_lexical_block
+; CHECK:     NULL
+
+; Abstract definition of `removed()`
+; CHECK:   DW_TAG_subprogram
+; CHECK:     DW_AT_name	("removed")
+; CHECK:     DW_AT_inline	(DW_INL_inlined)
+; CHECK:     DW_TAG_lexical_block
+; CHECK:       DW_TAG_variable
+; CHECK:         DW_AT_name	("A")
+; CHECK:         DW_AT_location	(DW_OP_addr 0x0)
+; CHECK:       NULL
+; CHECK:     NULL
+; CHECK:   DW_TAG_base_type
+
+; Abstract definition of `not_removed()`
+; CHECK:   DW_TAG_subprogram
+; CHECK:     DW_AT_name	("not_removed")
+; CHECK:     DW_AT_inline	(DW_INL_inlined)
+; CHECK:     DW_TAG_lexical_block
+; CHECK:       DW_TAG_variable
+; CHECK:         DW_AT_name	("B")
+; CHECK:         DW_AT_location	(DW_OP_addr 0x0)
+; CHECK:       NULL
+; CHECK:     NULL
+
+; Definition of foo().
+; CHECK:   DW_TAG_subprogram
+; CHECK:     DW_AT_name	("foo")
+; CHECK:     DW_TAG_lexical_block
+; CHECK:       DW_TAG_inlined_subroutine
+; CHECK:         DW_TAG_lexical_block
+; CHECK:         NULL
+; CHECK:       DW_TAG_inlined_subroutine
+; CHECK:         DW_TAG_lexical_block
+; CHECK:         NULL
+; CHECK:       DW_TAG_variable
+; CHECK:         DW_AT_name	("C")
+; CHECK:         DW_AT_location	(DW_OP_addr 0x0)
+; CHECK:       NULL
+; CHECK:     NULL
+; CHECK:   NULL
+
+target triple = "x86_64-unknown-linux-gnu"
+
+ at _ZZ11not_removedvE1B = internal global i32 0, align 4, !dbg !0
+ at _ZZ3foovE1C = internal global i32 0, align 4, !dbg !10
+ at _ZZ7removedvE1A = linkonce_odr dso_local global i32 0, align 4, !dbg !15
+
+define dso_local i32 @_Z11not_removedv() !dbg !4 {
+entry:
+  %0 = load i32, i32* @_ZZ11not_removedvE1B, align 4, !dbg !25
+  %inc = add nsw i32 %0, 1, !dbg !25
+  store i32 %inc, i32* @_ZZ11not_removedvE1B, align 4, !dbg !25
+  ret i32 %0, !dbg !26
+}
+
+define dso_local i32 @_Z3foov() !dbg !13 {
+entry:
+  %0 = load i32, i32* @_ZZ3foovE1C, align 4, !dbg !27
+  %inc = add nsw i32 %0, 1, !dbg !27
+  store i32 %inc, i32* @_ZZ3foovE1C, align 4, !dbg !27
+  %1 = load i32, i32* @_ZZ7removedvE1A, align 4, !dbg !28
+  %inc.i3 = add nsw i32 %1, 1, !dbg !28
+  store i32 %inc.i3, i32* @_ZZ7removedvE1A, align 4, !dbg !28
+  %add = add nsw i32 %inc, %1, !dbg !30
+  %2 = load i32, i32* @_ZZ11not_removedvE1B, align 4, !dbg !31
+  %inc.i = add nsw i32 %2, 1, !dbg !31
+  store i32 %inc.i, i32* @_ZZ11not_removedvE1B, align 4, !dbg !31
+  %add2 = add nsw i32 %add, %2, !dbg !33
+  ret i32 %add2, !dbg !34
+}
+
+!llvm.dbg.cu = !{!8}
+!llvm.module.flags = !{!19, !20, !21, !22, !23}
+!llvm.ident = !{!24}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "B", scope: !2, file: !3, line: 13, type: !7, isLocal: true, isDefinition: true)
+!2 = distinct !DILexicalBlock(scope: !4, file: !3, line: 12, column: 3)
+!3 = !DIFile(filename: "test_static.cpp", directory: "/")
+!4 = distinct !DISubprogram(name: "not_removed", linkageName: "_Z11not_removedv", scope: !3, file: !3, line: 11, type: !5, scopeLine: 11, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !8, retainedNodes: !35)
+!5 = !DISubroutineType(types: !6)
+!6 = !{!7}
+!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!8 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!9 = !{!15}
+!10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression())
+!11 = distinct !DIGlobalVariable(name: "C", scope: !12, file: !3, line: 20, type: !7, isLocal: true, isDefinition: true)
+!12 = distinct !DILexicalBlock(scope: !13, file: !3, line: 19, column: 3)
+!13 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !3, file: !3, line: 18, type: !5, scopeLine: 18, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !8, retainedNodes: !36)
+!14 = !{}
+!15 = !DIGlobalVariableExpression(var: !16, expr: !DIExpression())
+!16 = distinct !DIGlobalVariable(name: "A", scope: !17, file: !3, line: 5, type: !7, isLocal: false, isDefinition: true)
+!17 = distinct !DILexicalBlock(scope: !18, file: !3, line: 4, column: 3)
+!18 = distinct !DISubprogram(name: "removed", linkageName: "_Z7removedv", scope: !3, file: !3, line: 3, type: !5, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !8, retainedNodes: !9)
+!19 = !{i32 7, !"Dwarf Version", i32 4}
+!20 = !{i32 2, !"Debug Info Version", i32 3}
+!21 = !{i32 1, !"wchar_size", i32 4}
+!22 = !{i32 7, !"uwtable", i32 1}
+!23 = !{i32 7, !"frame-pointer", i32 2}
+!24 = !{!"clang version 14.0.0"}
+!25 = !DILocation(line: 14, column: 13, scope: !2)
+!26 = !DILocation(line: 14, column: 5, scope: !2)
+!27 = !DILocation(line: 21, column: 12, scope: !12)
+!28 = !DILocation(line: 6, column: 13, scope: !17, inlinedAt: !29)
+!29 = distinct !DILocation(line: 21, column: 18, scope: !12)
+!30 = !DILocation(line: 21, column: 16, scope: !12)
+!31 = !DILocation(line: 14, column: 13, scope: !2, inlinedAt: !32)
+!32 = distinct !DILocation(line: 21, column: 30, scope: !12)
+!33 = !DILocation(line: 21, column: 28, scope: !12)
+!34 = !DILocation(line: 21, column: 5, scope: !12)
+!35 = !{!0}
+!36 = !{!10}
diff --git a/llvm/test/DebugInfo/X86/namelist1.ll b/llvm/test/DebugInfo/X86/namelist1.ll
index 5132c894e8138..8e70809f67e9a 100644
--- a/llvm/test/DebugInfo/X86/namelist1.ll
+++ b/llvm/test/DebugInfo/X86/namelist1.ll
@@ -47,9 +47,9 @@ declare void @llvm.dbg.value(metadata, metadata, metadata)
 
 !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression(DW_OP_plus_uconst, 120))
 !1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 3, type: !9, isLocal: true, isDefinition: true)
-!2 = distinct !DISubprogram(name: "main", scope: !4, file: !3, line: 1, type: !7, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !4)
+!2 = distinct !DISubprogram(name: "main", scope: !4, file: !3, line: 1, type: !7, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !4, retainedNodes: !6)
 !3 = !DIFile(filename: "namelist.f90", directory: "/dir")
-!4 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, flags: "'+flang -g namelist.f90 -S -emit-llvm'", runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !5, nameTableKind: None)
+!4 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, flags: "'+flang -g namelist.f90 -S -emit-llvm'", runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, imports: !5, nameTableKind: None)
 !5 = !{}
 !6 = !{!0}
 !7 = !DISubroutineType(cc: DW_CC_program, types: !8)
diff --git a/llvm/test/DebugInfo/X86/sdag-dbgvalue-phi-use-4.ll b/llvm/test/DebugInfo/X86/sdag-dbgvalue-phi-use-4.ll
index 786c78d33337b..99c24b08c0d75 100644
--- a/llvm/test/DebugInfo/X86/sdag-dbgvalue-phi-use-4.ll
+++ b/llvm/test/DebugInfo/X86/sdag-dbgvalue-phi-use-4.ll
@@ -19,39 +19,39 @@
 ; INSTRREF-SAME:    debug-instr-number 2
 ; CHECK-NEXT:    [[REG3:%[0-9]+]]:gr32 = PHI
 ; INSTRREF-SAME:    debug-instr-number 3
-; INSTRREF-NEXT: DBG_INSTR_REF !13, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_fragment, 0, 32), dbg-instr-ref(1, 0)
-; INSTRREF-NEXT: DBG_INSTR_REF !13, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_fragment, 32, 32), dbg-instr-ref(2, 0)
-; INSTRREF-NEXT: DBG_INSTR_REF !13, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_fragment, 64, 16), dbg-instr-ref(3, 0)
-; INSTRREF-NEXT: DBG_INSTR_REF !12, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_fragment, 10, 32), dbg-instr-ref(1, 0)
-; INSTRREF-NEXT: DBG_INSTR_REF !12, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_fragment, 42, 13), dbg-instr-ref(2, 0)
-; DBGVALUE-NEXT: DBG_VALUE [[REG1]], $noreg,  !13, !DIExpression(DW_OP_LLVM_fragment, 0, 32)
-; DBGVALUE-NEXT: DBG_VALUE [[REG2]], $noreg,  !13, !DIExpression(DW_OP_LLVM_fragment, 32, 32)
-; DBGVALUE-NEXT: DBG_VALUE [[REG3]], $noreg,  !13, !DIExpression(DW_OP_LLVM_fragment, 64, 16)
-; DBGVALUE-NEXT: DBG_VALUE [[REG1]], $noreg,  !12, !DIExpression(DW_OP_LLVM_fragment, 10, 32)
-; DBGVALUE-NEXT: DBG_VALUE [[REG2]], $noreg,  !12, !DIExpression(DW_OP_LLVM_fragment, 42, 13)
+; INSTRREF-NEXT: DBG_INSTR_REF !16, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_fragment, 0, 32), dbg-instr-ref(1, 0)
+; INSTRREF-NEXT: DBG_INSTR_REF !16, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_fragment, 32, 32), dbg-instr-ref(2, 0)
+; INSTRREF-NEXT: DBG_INSTR_REF !16, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_fragment, 64, 16), dbg-instr-ref(3, 0)
+; INSTRREF-NEXT: DBG_INSTR_REF !15, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_fragment, 10, 32), dbg-instr-ref(1, 0)
+; INSTRREF-NEXT: DBG_INSTR_REF !15, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_fragment, 42, 13), dbg-instr-ref(2, 0)
+; DBGVALUE-NEXT: DBG_VALUE [[REG1]], $noreg,  !16, !DIExpression(DW_OP_LLVM_fragment, 0, 32)
+; DBGVALUE-NEXT: DBG_VALUE [[REG2]], $noreg,  !16, !DIExpression(DW_OP_LLVM_fragment, 32, 32)
+; DBGVALUE-NEXT: DBG_VALUE [[REG3]], $noreg,  !16, !DIExpression(DW_OP_LLVM_fragment, 64, 16)
+; DBGVALUE-NEXT: DBG_VALUE [[REG1]], $noreg,  !15, !DIExpression(DW_OP_LLVM_fragment, 10, 32)
+; DBGVALUE-NEXT: DBG_VALUE [[REG2]], $noreg,  !15, !DIExpression(DW_OP_LLVM_fragment, 42, 13)
 ; CHECK-NOT:  DBG_
 
 target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
 target triple = "i686-w64-windows-gnu"
 
 ; Function Attrs: nounwind readnone
-define dso_local i64 @nextafterl(i80 %a, i1 %arg) local_unnamed_addr #0 !dbg !6 {
+define dso_local i64 @nextafterl(i80 %a, i1 %arg) local_unnamed_addr #0 !dbg !5 {
 entry:
-  br i1 %arg, label %if.else, label %if.then13, !dbg !28
+  br i1 %arg, label %if.else, label %if.then13, !dbg !27
 
 if.then13:                                        ; preds = %entry
-  %u.sroa.0.8.insert.insert = or i80 %a, 2222, !dbg !29
-  br label %if.end36, !dbg !33
+  %u.sroa.0.8.insert.insert = or i80 %a, 2222, !dbg !28
+  br label %if.end36, !dbg !32
 
 if.else:                                          ; preds = %entry
   br label %if.end36
 
 if.end36:                                         ; preds = %if.else, %if.then13
   %u.sroa.0.1.in = phi i80 [ %u.sroa.0.8.insert.insert, %if.then13 ], [ 1234567, %if.else ]
-  call void @llvm.dbg.value(metadata i80 %u.sroa.0.1.in, metadata !13, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 80)), !dbg !34
-  call void @llvm.dbg.value(metadata i80 %u.sroa.0.1.in, metadata !12, metadata !DIExpression(DW_OP_LLVM_fragment, 10, 45)), !dbg !34
-  %u.sroa.0.0.extract.ashr = ashr i80 %u.sroa.0.1.in, 8, !dbg !35
-  %u.sroa.0.0.extract.trunc = trunc i80 %u.sroa.0.0.extract.ashr to i64, !dbg !35
+  call void @llvm.dbg.value(metadata i80 %u.sroa.0.1.in, metadata !16, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 80)), !dbg !33
+  call void @llvm.dbg.value(metadata i80 %u.sroa.0.1.in, metadata !15, metadata !DIExpression(DW_OP_LLVM_fragment, 10, 45)), !dbg !33
+  %u.sroa.0.0.extract.ashr = ashr i80 %u.sroa.0.1.in, 8, !dbg !34
+  %u.sroa.0.0.extract.trunc = trunc i80 %u.sroa.0.0.extract.ashr to i64, !dbg !34
   ret i64 %u.sroa.0.0.extract.trunc
 }
 
@@ -62,42 +62,41 @@ attributes #0 = { nounwind readnone }
 attributes #1 = { nounwind readnone speculatable }
 
 !llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!26, !27}
+!llvm.module.flags = !{!4, !3}
 
-!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 7.0.0 (trunk 330808) (llvm/trunk 330813)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3)
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 7.0.0 (trunk 330808) (llvm/trunk 330813)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !2)
 !1 = !DIFile(filename: "pr37321.c", directory: "")
 !2 = !{}
-!3 = !{!4}
-!4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression())
-!5 = distinct !DIGlobalVariable(name: "normal_bit", scope: !6, file: !1, line: 31, type: !25, isLocal: true, isDefinition: true)
-!6 = distinct !DISubprogram(name: "nextafterl", scope: !1, file: !1, line: 17, type: !7, isLocal: false, isDefinition: true, scopeLine: 18, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !10)
-!7 = !DISubroutineType(types: !8)
-!8 = !{!9, !9, !9}
-!9 = !DIBasicType(name: "long double", size: 96, encoding: DW_ATE_float)
-!10 = !{!11, !12, !13}
-!11 = !DILocalVariable(name: "x", arg: 1, scope: !6, file: !1, line: 17, type: !9)
-!12 = !DILocalVariable(name: "y", arg: 2, scope: !6, file: !1, line: 17, type: !9)
-!13 = !DILocalVariable(name: "u", scope: !6, file: !1, line: 27, type: !14)
-!14 = distinct !DICompositeType(tag: DW_TAG_union_type, scope: !6, file: !1, line: 19, size: 128, elements: !15)
-!15 = !{!16, !17}
-!16 = !DIDerivedType(tag: DW_TAG_member, name: "ld", scope: !14, file: !1, line: 20, baseType: !9, size: 96)
-!17 = !DIDerivedType(tag: DW_TAG_member, name: "parts", scope: !14, file: !1, line: 26, baseType: !18, size: 128)
-!18 = distinct !DICompositeType(tag: DW_TAG_structure_type, scope: !14, file: !1, line: 21, size: 128, elements: !19)
-!19 = !{!20, !22, !24}
-!20 = !DIDerivedType(tag: DW_TAG_member, name: "mantissa", scope: !18, file: !1, line: 23, baseType: !21, size: 64)
-!21 = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned)
-!22 = !DIDerivedType(tag: DW_TAG_member, name: "expn", scope: !18, file: !1, line: 24, baseType: !23, size: 16, offset: 64)
-!23 = !DIBasicType(name: "unsigned short", size: 16, encoding: DW_ATE_unsigned)
-!24 = !DIDerivedType(tag: DW_TAG_member, name: "pad", scope: !18, file: !1, line: 25, baseType: !23, size: 16, offset: 80)
-!25 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !21)
-!26 = !{i32 2, !"Debug Info Version", i32 3}
-!27 = !{i32 1, !"wchar_size", i32 2}
-!28 = !DILocation(line: 47, column: 7, scope: !6)
-!29 = !DILocation(line: 51, column: 14, scope: !30)
-!30 = distinct !DILexicalBlock(scope: !31, file: !1, line: 50, column: 11)
-!31 = distinct !DILexicalBlock(scope: !32, file: !1, line: 48, column: 5)
-!32 = distinct !DILexicalBlock(scope: !6, file: !1, line: 47, column: 7)
-!33 = !DILocation(line: 51, column: 2, scope: !30)
-!34 = !DILocation(line: 27, column: 5, scope: !6)
-!35 = !DILocation(line: 63, column: 22, scope: !36)
-!36 = distinct !DILexicalBlock(scope: !6, file: !1, line: 62, column: 7)
+!3 = !{i32 1, !"wchar_size", i32 2}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = distinct !DISubprogram(name: "nextafterl", scope: !1, file: !1, line: 17, type: !6, isLocal: false, isDefinition: true, scopeLine: 18, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !9)
+!6 = !DISubroutineType(types: !7)
+!7 = !{!8, !8, !8}
+!8 = !DIBasicType(name: "long double", size: 96, encoding: DW_ATE_float)
+!9 = !{!10, !14, !15, !16}
+!10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression())
+!11 = distinct !DIGlobalVariable(name: "normal_bit", scope: !5, file: !1, line: 31, type: !12, isLocal: true, isDefinition: true)
+!12 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !13)
+!13 = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned)
+!14 = !DILocalVariable(name: "x", arg: 1, scope: !5, file: !1, line: 17, type: !8)
+!15 = !DILocalVariable(name: "y", arg: 2, scope: !5, file: !1, line: 17, type: !8)
+!16 = !DILocalVariable(name: "u", scope: !5, file: !1, line: 27, type: !24)
+!17 = !DIDerivedType(tag: DW_TAG_member, name: "parts", scope: !24, file: !1, line: 26, baseType: !18, size: 128)
+!18 = distinct !DICompositeType(tag: DW_TAG_structure_type, scope: !24, file: !1, line: 21, size: 128, elements: !19)
+!19 = !{!20, !21, !23}
+!20 = !DIDerivedType(tag: DW_TAG_member, name: "mantissa", scope: !18, file: !1, line: 23, baseType: !13, size: 64)
+!21 = !DIDerivedType(tag: DW_TAG_member, name: "expn", scope: !18, file: !1, line: 24, baseType: !22, size: 16, offset: 64)
+!22 = !DIBasicType(name: "unsigned short", size: 16, encoding: DW_ATE_unsigned)
+!23 = !DIDerivedType(tag: DW_TAG_member, name: "pad", scope: !18, file: !1, line: 25, baseType: !22, size: 16, offset: 80)
+!24 = distinct !DICompositeType(tag: DW_TAG_union_type, scope: !5, file: !1, line: 19, size: 128, elements: !25)
+!25 = !{!26, !17}
+!26 = !DIDerivedType(tag: DW_TAG_member, name: "ld", scope: !24, file: !1, line: 20, baseType: !8, size: 96)
+!27 = !DILocation(line: 47, column: 7, scope: !5)
+!28 = !DILocation(line: 51, column: 14, scope: !29)
+!29 = distinct !DILexicalBlock(scope: !30, file: !1, line: 50, column: 11)
+!30 = distinct !DILexicalBlock(scope: !31, file: !1, line: 48, column: 5)
+!31 = distinct !DILexicalBlock(scope: !5, file: !1, line: 47, column: 7)
+!32 = !DILocation(line: 51, column: 2, scope: !29)
+!33 = !DILocation(line: 27, column: 5, scope: !5)
+!34 = !DILocation(line: 63, column: 22, scope: !35)
+!35 = distinct !DILexicalBlock(scope: !5, file: !1, line: 62, column: 7)
diff --git a/llvm/test/DebugInfo/duplicate_dbgvalue.ll b/llvm/test/DebugInfo/duplicate_dbgvalue.ll
index 8fb3eeb74e012..21d97aef2c810 100644
--- a/llvm/test/DebugInfo/duplicate_dbgvalue.ll
+++ b/llvm/test/DebugInfo/duplicate_dbgvalue.ll
@@ -107,11 +107,11 @@ declare void @llvm.dbg.value(metadata, metadata, metadata)
 
 !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
 !1 = distinct !DIGlobalVariable(name: "res", scope: !2, file: !3, type: !9, isLocal: true, isDefinition: true)
-!2 = distinct !DISubprogram(name: "main", scope: !4, file: !3, line: 1, type: !12, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !4)
+!2 = distinct !DISubprogram(name: "main", scope: !4, file: !3, line: 1, type: !12, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !4, retainedNodes: !60)
 !3 = !DIFile(filename: "duplicate-dbgvalue.f90", directory: "/dir")
 !4 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !5)
 !5 = !{}
-!6 = !{!0, !7, !10}
+!6 = !{!7, !10}
 !7 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression())
 !8 = distinct !DIGlobalVariable(name: "res", scope: !4, file: !3, type: !9, isLocal: true, isDefinition: true)
 !9 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed)
@@ -165,3 +165,4 @@ declare void @llvm.dbg.value(metadata, metadata, metadata)
 !57 = !{!"unlimited ptr", !58, i64 0}
 !58 = !{!"Flang FAA 3"}
 !59 = !DILocation(line: 15, column: 1, scope: !52)
+!60 = !{!0}
diff --git a/llvm/test/Instrumentation/InstrProfiling/debug-info-correlate.ll b/llvm/test/Instrumentation/InstrProfiling/debug-info-correlate.ll
index 84eaab33701a4..c1a610791be2b 100644
--- a/llvm/test/Instrumentation/InstrProfiling/debug-info-correlate.ll
+++ b/llvm/test/Instrumentation/InstrProfiling/debug-info-correlate.ll
@@ -20,7 +20,7 @@
 
 define void @_Z3foov() !dbg !12 {
   call void @llvm.instrprof.increment(ptr @__profn_foo, i64 12345678, i32 2, i32 0)
-  ret void
+  ret void, !dbg !17
 }
 
 declare void @llvm.instrprof.increment(ptr, i64, i32, i32)
@@ -46,6 +46,7 @@ declare void @llvm.instrprof.increment(ptr, i64, i32, i32)
 !14 = !DISubroutineType(types: !15)
 !15 = !{null}
 !16 = !{}
+!17 = !DILocation(line: 1, scope: !12)
 
 ; CHECK-DWARF: DW_TAG_compile_unit
 ; CHECK-DWARF:   DW_TAG_subprogram
diff --git a/llvm/test/Transforms/Util/clone-dicompileunit.ll b/llvm/test/Transforms/Util/clone-dicompileunit.ll
index c417aafdaced3..ba40aa32c1428 100644
--- a/llvm/test/Transforms/Util/clone-dicompileunit.ll
+++ b/llvm/test/Transforms/Util/clone-dicompileunit.ll
@@ -25,18 +25,23 @@
 
 ; CHECK: DICompileUnit
 ; CHECK-NOT: DICompileUnit
+; CHECK: DISubprogram
+; CHECK-NOT: DICompileUnit
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux"
 
+define void @foo() !dbg !6 {
+  ret void
+}
+
 !llvm.dbg.cu = !{!0}
 !llvm.module.flags = !{!28, !29}
 !llvm.ident = !{!30}
 
-!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 5.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3)
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 5.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !2)
 !1 = !DIFile(filename: "p.cpp", directory: "/usr/local/google/home/pcc/b682773-2-repro/small2")
 !2 = !{}
-!3 = !{!4}
 !4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression())
 !5 = distinct !DIGlobalVariable(name: "a", scope: !6, file: !1, line: 5, type: !27, isLocal: true, isDefinition: true)
 !6 = distinct !DISubprogram(name: "m_fn2<B>", linkageName: "_ZN1A5m_fn2IZ3foovE1BEEvv", scope: !7, file: !1, line: 5, type: !8, isLocal: true, isDefinition: true, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: true, unit: !0, templateParams: !11, declaration: !23, retainedNodes: !24)
@@ -57,7 +62,7 @@ target triple = "x86_64-unknown-linux"
 !21 = !{null, !22}
 !22 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
 !23 = !DISubprogram(name: "m_fn2<B>", linkageName: "_ZN1A5m_fn2IZ3foovE1BEEvv", scope: !7, file: !1, line: 5, type: !8, isLocal: false, isDefinition: false, scopeLine: 5, flags: DIFlagPublic | DIFlagPrototyped, isOptimized: true, templateParams: !11)
-!24 = !{!25}
+!24 = !{!25, !4}
 !25 = !DILocalVariable(name: "this", arg: 1, scope: !6, type: !26, flags: DIFlagArtificial | DIFlagObjectPointer)
 !26 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
 !27 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/Inputs/ThreadLocalStorage.ll b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/Inputs/ThreadLocalStorage.ll
index 45b7574f1843e..aeee0b3d95764 100644
--- a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/Inputs/ThreadLocalStorage.ll
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/Inputs/ThreadLocalStorage.ll
@@ -25,7 +25,7 @@ declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull)
 !1 = distinct !DIGlobalVariable(name: "TGlobal", scope: !2, file: !3, line: 1, type: !7, isLocal: false, isDefinition: true)
 !2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, emissionKind: FullDebug, globals: !4)
 !3 = !DIFile(filename: "ThreadLocalStorage.cpp", directory: "")
-!4 = !{!0, !5, !8}
+!4 = !{!0, !5}
 !5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression())
 !6 = distinct !DIGlobalVariable(name: "NGlobal", scope: !2, file: !3, line: 2, type: !7, isLocal: false, isDefinition: true)
 !7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
@@ -34,7 +34,7 @@ declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull)
 !10 = distinct !DISubprogram(name: "test", scope: !3, file: !3, line: 3, type: !11, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !13)
 !11 = !DISubroutineType(types: !12)
 !12 = !{null}
-!13 = !{}
+!13 = !{!8}
 !14 = !{i32 7, !"Dwarf Version", i32 5}
 !15 = !{i32 2, !"Debug Info Version", i32 3}
 !22 = !DILocation(line: 5, scope: !10)
diff --git a/llvm/unittests/Transforms/Utils/CloningTest.cpp b/llvm/unittests/Transforms/Utils/CloningTest.cpp
index 8c138be840ed7..cdea7740ff460 100644
--- a/llvm/unittests/Transforms/Utils/CloningTest.cpp
+++ b/llvm/unittests/Transforms/Utils/CloningTest.cpp
@@ -833,7 +833,7 @@ TEST(CloneFunction, CloneFunctionWithRetainedNodes) {
     !6 = distinct !DILexicalBlock(scope: !4, file: !1, line: 1)
     !7 = !DILocation(line: 1, scope: !6, inlinedAt: !8)
     !8 = !DILocation(line: 10, scope: !3)
-    !9 = !{!15, !17, !18, !23, !26, !28, !30}
+    !9 = !{!15, !17, !18, !23, !26, !28, !30, !31}
     !14 = distinct !DICompositeType(tag: DW_TAG_enumeration_type, scope: !0, file: !1, line: 13, size: 200, elements: !{})
     !15 = !DILocalVariable(name: "a", scope: !3)
     !16 = distinct !DICompositeType(tag: DW_TAG_enumeration_type, scope: !3, file: !1, line: 13, size: 208, elements: !{})
@@ -849,6 +849,8 @@ TEST(CloneFunction, CloneFunctionWithRetainedNodes) {
     !28 = !DILocalVariable(name: "ptr", scope: !3, type: !27)
     !29 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !27)
     !30 = !DILocalVariable(name: "const_ptr", scope: !3, type: !29)
+    !31 = !DIGlobalVariableExpression(var: !32, expr: !DIExpression())
+    !32 = distinct !DIGlobalVariable(name: "global_var", scope: !3, file: !1, line: 5, type: !22, isLocal: true, isDefinition: true)
   )";
 
   LLVMContext Context;
@@ -876,8 +878,10 @@ TEST(CloneFunction, CloneFunctionWithRetainedNodes) {
   DISubprogram *ClonedSP = ClonedFunc->getSubprogram();
   EXPECT_NE(FuncSP, nullptr);
   EXPECT_NE(ClonedSP, nullptr);
-  EXPECT_EQ(FuncSP->getRetainedNodes().size(), 7u);
-  EXPECT_EQ(FuncSP->getRetainedNodes().size(),
+  EXPECT_EQ(FuncSP->getRetainedNodes().size(), 8u);
+  // DIGlobalVariableExpressions should be excluded from retainedNodes of the
+  // cloned DISubprogram, as we don't clone them.
+  EXPECT_EQ(FuncSP->getRetainedNodes().size() - 1,
             ClonedSP->getRetainedNodes().size());
 
   // Ensure that Orig node is a clone of Copy by checking that they are
@@ -892,17 +896,20 @@ TEST(CloneFunction, CloneFunctionWithRetainedNodes) {
 
   // Check that retained nodes are cloned.
   unsigned I = 0;
-  auto CheckRetainedNode = [&](auto *Node) {
+  auto CheckRetainedNode = [&](auto *Copy) {
     // The order of retained nodes should be preserved.
-    auto *Copy =
-        cast<std::decay_t<decltype(*Node)>>(ClonedSP->getRetainedNodes()[I]);
+    auto *Node =
+        cast<std::decay_t<decltype(*Copy)>>(FuncSP->getRetainedNodes()[I]);
 
     CheckNodeIsCloned(Node, Copy);
 
     ++I;
   };
-  FuncSP->forEachRetainedNode(CheckRetainedNode, CheckRetainedNode,
-                              CheckRetainedNode, CheckRetainedNode);
+  ClonedSP->forEachRetainedNode(
+      CheckRetainedNode, CheckRetainedNode, CheckRetainedNode,
+      CheckRetainedNode, [](MDNode *_) {
+        FAIL() << "DIGlobalVariableExpression should not be cloned.";
+      });
 
   auto ToDerived = [](const DIType *Ty) { return cast<DIDerivedType>(Ty); };
 
@@ -1187,6 +1194,15 @@ TEST_F(CloneModule, Subprogram) {
   EXPECT_EQ(SP->getName(), "f");
   EXPECT_EQ(SP->getFile()->getFilename(), "filename.c");
   EXPECT_EQ(SP->getLine(), (unsigned)4);
+
+  // Check static locals have the correct scope.
+  MDNodeArray LocalDeclsArray = SP->getRetainedNodes();
+  EXPECT_EQ(LocalDeclsArray.size(), 2U);
+  for (auto *Node : LocalDeclsArray) {
+    auto *GVExpr = cast<DIGlobalVariableExpression>(Node);
+    DIGlobalVariable *GV = GVExpr->getVariable();
+    EXPECT_EQ(GV->getScope(), SP);
+  }
 }
 
 TEST_F(CloneModule, FunctionDeclarationMetadata) {
@@ -1244,14 +1260,6 @@ TEST_F(CloneModule, CompileUnit) {
   DISubprogram *SP = NewM->getFunction("f")->getSubprogram();
   EXPECT_TRUE(SP != nullptr);
   EXPECT_EQ(SP->getUnit(), CU);
-
-  // Check globals listed in CU have the correct scope
-  DIGlobalVariableExpressionArray GlobalArray = CU->getGlobalVariables();
-  EXPECT_EQ(GlobalArray.size(), 2U);
-  for (DIGlobalVariableExpression *GVExpr : GlobalArray) {
-    DIGlobalVariable *GV = GVExpr->getVariable();
-    EXPECT_EQ(GV->getScope(), SP);
-  }
 }
 
 TEST_F(CloneModule, Comdat) {
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index d53f522e646fb..2c9a9f4225b02 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -702,7 +702,7 @@ def LLVM_DISubprogramAttr : LLVM_Attr<"DISubprogram", "di_subprogram",
     OptionalParameter<"unsigned">:$scopeLine,
     OptionalParameter<"DISubprogramFlags">:$subprogramFlags,
     OptionalParameter<"DISubroutineTypeAttr">:$type,
-    OptionalArrayRefParameter<"DINodeAttr">:$retainedNodes,
+    OptionalArrayRefParameter<"Attribute">:$retainedNodes,
     OptionalArrayRefParameter<"DINodeAttr">:$annotations
   );
   let builders = [
@@ -711,7 +711,7 @@ def LLVM_DISubprogramAttr : LLVM_Attr<"DISubprogram", "di_subprogram",
       "DIScopeAttr":$scope, "StringAttr":$name, "StringAttr":$linkageName,
       "DIFileAttr":$file, "unsigned":$line, "unsigned":$scopeLine,
       "DISubprogramFlags":$subprogramFlags, "DISubroutineTypeAttr":$type,
-      "ArrayRef<DINodeAttr>":$retainedNodes, "ArrayRef<DINodeAttr>":$annotations
+      "ArrayRef<Attribute>":$retainedNodes, "ArrayRef<DINodeAttr>":$annotations
     ), [{
       return $_get($_ctxt, /*recId=*/nullptr, /*isRecSelf=*/false, id, compileUnit,
                    scope, name, linkageName, file, line, scopeLine,
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialectBytecode.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialectBytecode.td
index d4e1450d2f516..409c61566e767 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialectBytecode.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialectBytecode.td
@@ -162,7 +162,7 @@ def DISubprogramAttr : DialectAttribute<(attr
   EnumClassFlag<"DISubprogramFlags", "getSubprogramFlags()">:$_rawflags,
   LocalVar<"DISubprogramFlags", "(DISubprogramFlags)_rawflags">:$subprogramFlags,
   OptionalAttribute<"DISubroutineTypeAttr">:$type,
-  OptionalArrayRef<"DINodeAttr">:$retainedNodes,
+  OptionalArrayRef<"Attribute">:$retainedNodes,
   OptionalArrayRef<"DINodeAttr">:$annotations
 )>;
 
diff --git a/mlir/lib/CAPI/Dialect/LLVM.cpp b/mlir/lib/CAPI/Dialect/LLVM.cpp
index dbd4b1213491b..64addcdcc5e46 100644
--- a/mlir/lib/CAPI/Dialect/LLVM.cpp
+++ b/mlir/lib/CAPI/Dialect/LLVM.cpp
@@ -458,7 +458,7 @@ MlirAttribute mlirLLVMDISubprogramAttrGet(
       cast<DISubroutineTypeAttr>(unwrap(type)),
       llvm::map_to_vector(
           unwrapList(nRetainedNodes, retainedNodes, nodesStorage),
-          llvm::CastTo<DINodeAttr>),
+          llvm::CastTo<Attribute>),
       llvm::map_to_vector(
           unwrapList(nAnnotations, annotations, annotationsStorage),
           llvm::CastTo<DINodeAttr>)));
diff --git a/mlir/lib/Target/LLVMIR/DebugImporter.cpp b/mlir/lib/Target/LLVMIR/DebugImporter.cpp
index 1a6703fd4056a..072ea2c386112 100644
--- a/mlir/lib/Target/LLVMIR/DebugImporter.cpp
+++ b/mlir/lib/Target/LLVMIR/DebugImporter.cpp
@@ -245,9 +245,14 @@ DISubprogramAttr DebugImporter::translateImpl(llvm::DISubprogram *node) {
     return nullptr;
 
   // Convert the retained nodes but drop all of them if one of them is invalid.
-  SmallVector<DINodeAttr> retainedNodes;
-  for (llvm::DINode *retainedNode : node->getRetainedNodes())
+  SmallVector<Attribute> retainedNodes;
+  auto add = [this, &retainedNodes](llvm::DINode *retainedNode) {
     retainedNodes.push_back(translate(retainedNode));
+  };
+  auto addGVE = [this, &retainedNodes](llvm::DIGlobalVariableExpression *GVE) {
+    retainedNodes.push_back(translateGlobalVariableExpression(GVE));
+  };
+  node->forEachRetainedNode(add, add, add, add, addGVE);
   if (llvm::is_contained(retainedNodes, nullptr))
     retainedNodes.clear();
 
diff --git a/mlir/lib/Target/LLVMIR/DebugTranslation.cpp b/mlir/lib/Target/LLVMIR/DebugTranslation.cpp
index dce5806d48034..5c6bd2d72c126 100644
--- a/mlir/lib/Target/LLVMIR/DebugTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/DebugTranslation.cpp
@@ -112,6 +112,24 @@ DebugTranslation::getMDTupleOrNull(ArrayRef<DINodeAttr> elements) {
   return llvm::MDNode::get(llvmCtx, llvmElements);
 }
 
+llvm::MDTuple *
+DebugTranslation::getRetainedNodesOrNull(ArrayRef<Attribute> retainedNodes) {
+  if (retainedNodes.empty())
+    return nullptr;
+  SmallVector<llvm::Metadata *> llvmElements = llvm::map_to_vector(
+      retainedNodes, [&](Attribute attr) -> llvm::Metadata * {
+        if (DIGlobalVariableExpressionAttr GVE =
+                dyn_cast<DIGlobalVariableExpressionAttr>(attr))
+          return translateGlobalVariableExpression(GVE);
+
+        auto diAttr = dyn_cast<DINodeAttr>(attr);
+        if (!diAttr)
+          llvm_unreachable("unknown retained node kind");
+        return translate(diAttr);
+      });
+  return llvm::MDNode::get(llvmCtx, llvmElements);
+}
+
 llvm::DIBasicType *DebugTranslation::translateImpl(DIBasicTypeAttr attr) {
   return llvm::DIBasicType::get(
       llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()),
@@ -350,7 +368,7 @@ llvm::DISubprogram *DebugTranslation::translateImpl(DISubprogramAttr attr) {
       /*ThisAdjustment=*/0, llvm::DINode::FlagZero,
       static_cast<llvm::DISubprogram::DISPFlags>(attr.getSubprogramFlags()),
       compileUnit, /*TemplateParams=*/nullptr, /*Declaration=*/nullptr,
-      getMDTupleOrNull(attr.getRetainedNodes()), nullptr,
+      getRetainedNodesOrNull(attr.getRetainedNodes()), nullptr,
       getMDTupleOrNull(attr.getAnnotations()));
   if (attr.getId())
     distinctAttrToNode.try_emplace(attr.getId(), node);
diff --git a/mlir/lib/Target/LLVMIR/DebugTranslation.h b/mlir/lib/Target/LLVMIR/DebugTranslation.h
index b690d4820d7b0..3809d75fa4af0 100644
--- a/mlir/lib/Target/LLVMIR/DebugTranslation.h
+++ b/mlir/lib/Target/LLVMIR/DebugTranslation.h
@@ -113,6 +113,10 @@ class DebugTranslation {
   /// `elements` is empty.
   llvm::MDTuple *getMDTupleOrNull(ArrayRef<DINodeAttr> elements);
 
+  /// Consturct a DISubprogram's retainedNodes metadata node from the
+  /// `retainedNodes`. Returns nullptr if `retainedNodes` is empty.
+  llvm::MDTuple *getRetainedNodesOrNull(ArrayRef<Attribute> retainedNodes);
+
   /// Constructs a DIExpression metadata node from the DIExpressionAttr. Returns
   /// nullptr if `DIExpressionAttr` is null.
   llvm::DIExpression *getExpressionAttrOrNull(DIExpressionAttr attr);
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index f4a6e5f6fc8f6..dd95c41cfc523 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -1167,7 +1167,9 @@ convertMLIRAttributesToLLVM(Location loc, llvm::LLVMContext &ctx,
 
 LogicalResult ModuleTranslation::convertGlobalsAndAliases() {
   // Mapping from compile unit to its respective set of global variables.
-  DenseMap<llvm::DICompileUnit *, SmallVector<llvm::Metadata *>> allGVars;
+  DenseMap<llvm::DICompileUnit *, SmallVector<llvm::Metadata *>> globalGVars;
+  // Mapping from subprogram to its respective set of static local variables.
+  DenseMap<llvm::DISubprogram *, SmallVector<llvm::Metadata *>> staticLocals;
 
   // First, create all global variables and global aliases in LLVM IR. A global
   // or alias body may refer to another global/alias or itself, so all the
@@ -1255,7 +1257,7 @@ LogicalResult ModuleTranslation::convertGlobalsAndAliases() {
         //
         // 3. For entities like static local variables in C or variable with
         // SAVE attribute in Fortran, the scope hierarchy can be
-        // variable -> DISubprogram -> DICompileUnit
+        // variable (-> DILocalScope)* -> DISubprogram
         llvm::DIScope *scope = diGlobalVar->getScope();
         if (auto *mod = dyn_cast_if_present<llvm::DIModule>(scope))
           scope = mod->getScope();
@@ -1263,15 +1265,22 @@ LogicalResult ModuleTranslation::convertGlobalsAndAliases() {
           if (auto *sp =
                   dyn_cast_if_present<llvm::DISubprogram>(cb->getScope()))
             scope = sp->getUnit();
-        } else if (auto *sp = dyn_cast_if_present<llvm::DISubprogram>(scope))
-          scope = sp->getUnit();
+        } else if (auto *lbb =
+                       dyn_cast_if_present<llvm::DILexicalBlockBase>(scope))
+          scope = lbb->getSubprogram();
 
-        // Get the compile unit (scope) of the the global variable.
+        // Get the compile unit (scope) of the the global variable, or the
+        // subprogram of the static local variable.
         if (llvm::DICompileUnit *compileUnit =
                 dyn_cast_if_present<llvm::DICompileUnit>(scope)) {
           // Update the compile unit with this incoming global variable
           // expression during the finalizing step later.
-          allGVars[compileUnit].push_back(diGlobalExpr);
+          globalGVars[compileUnit].push_back(diGlobalExpr);
+        } else if (llvm::DISubprogram *sp =
+                       dyn_cast_if_present<llvm::DISubprogram>(scope)) {
+          // Update the subprogram with this incoming static local variable
+          // expression during the finalizing step later.
+          staticLocals[sp].push_back(diGlobalExpr);
         }
       }
     }
@@ -1441,10 +1450,14 @@ LogicalResult ModuleTranslation::convertGlobalsAndAliases() {
 
   // Finally, update the compile units their respective sets of global variables
   // created earlier.
-  for (const auto &[compileUnit, globals] : allGVars) {
+  for (const auto &[compileUnit, globals] : globalGVars)
     compileUnit->replaceGlobalVariables(
         llvm::MDTuple::get(getLLVMContext(), globals));
-  }
+
+  // And update the subprograms with their respective sets of static local
+  // variables.
+  for (const auto &[sp, globals] : staticLocals)
+    sp->retainNodes(globals.begin(), globals.end());
 
   // Convert global alias bodies.
   for (auto op : getModuleBody(mlirModule).getOps<LLVM::AliasOp>()) {
diff --git a/mlir/test/Target/LLVMIR/llvmir-debug.mlir b/mlir/test/Target/LLVMIR/llvmir-debug.mlir
index 95895e3e56a05..e2a39516aae1d 100644
--- a/mlir/test/Target/LLVMIR/llvmir-debug.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir-debug.mlir
@@ -354,10 +354,12 @@ llvm.mlir.global external @module_global() {dbg_exprs = [#llvm.di_global_variabl
 // -----
 
 // CHECK: @func_global = external global i64, !dbg {{.*}}
-// CHECK-DAG: ![[CU:.*]] = distinct !DICompileUnit({{.*}}globals: ![[GVALS:[0-9]+]], debugInfoForProfiling: true)
-// CHECK-DAG: ![[SP:.*]] = distinct !DISubprogram(name: "fn_with_gl"{{.*}}unit: ![[CU]])
+// CHECK-DAG: ![[SP:.*]] = distinct !DISubprogram(name: "fn_with_gl"{{.*}}unit: ![[CU:.*]], {{.*}}retainedNodes: ![[GVALS:.*]])
 // CHECK-DAG: ![[GVAR:.*]] = distinct !DIGlobalVariable(name: "func_global"{{.*}}, scope: ![[SP]]{{.*}})
 // CHECK-DAG: ![[GEXPR:.*]] = !DIGlobalVariableExpression(var: ![[GVAR]], expr: !DIExpression())
+// CHECK-DAG: ![[CU]] = distinct !DICompileUnit(
+// CHECK-NOT:     globals:
+// CHECK-SAME:    emissionKind: FullDebug, debugInfoForProfiling: true)
 // CHECK-DAG: ![[GVALS]] = !{![[GEXPR]]}
 
 #file = #llvm.di_file<"test.f90" in "existence">

>From 85f5e0c0e22001d95d99a4ed175f0808a36a157a Mon Sep 17 00:00:00 2001
From: Vladislav Dzhidzhoev <vdzhidzhoev at accesssoftek.com>
Date: Tue, 31 Mar 2026 15:43:17 +0200
Subject: [PATCH 2/3] Fix instrprof-debug-info-correlate-warnings.ll

---
 ...instrprof-debug-info-correlate-warnings.ll | 211 ++++++++++--------
 1 file changed, 124 insertions(+), 87 deletions(-)

diff --git a/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate-warnings.ll b/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate-warnings.ll
index 7a8569975c82b..6e5542f164bb2 100644
--- a/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate-warnings.ll
+++ b/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate-warnings.ll
@@ -1,7 +1,7 @@
 ; RUN: split-file %s %t
 ; RUN: %clang %t/a.ll -o %t/a.out
-; RUN: llvm-profdata merge --debug-info=%t/a.out %t/a.proftext --max-debug-info-correlation-warnings=2 -o %t/a.profdata 2>&1 | FileCheck %s --implicit-check-not=warning --check-prefixes=CHECK,LIMIT
 ; RUN: llvm-profdata merge --debug-info=%t/a.out %t/a.proftext --max-debug-info-correlation-warnings=0 -o %t/a.profdata 2>&1 | FileCheck %s --implicit-check-not=warning --check-prefixes=CHECK,NOLIMIT
+; RUN: llvm-profdata merge --debug-info=%t/a.out %t/a.proftext --max-debug-info-correlation-warnings=2 -o %t/a.profdata 2>&1 | FileCheck %s --implicit-check-not=warning --check-prefixes=CHECK,LIMIT
 
 ; CHECK: warning: Incomplete DIE for function None:
 ; CHECK: warning: Incomplete DIE for function no_cfg: CFGHash=None
@@ -21,7 +21,8 @@ void no_name() {}
 void no_cfg() {}
 void no_counter() {}
 void no_profc() {}
-void no_func() {}
+__attribute__((always_inline)) void no_func() {}
+void use_func() { no_func(); }
 
 // NOTE: After generating the IR below, manually remove the follwing pieces
 // 1. Remove "@removed" function and "@__profc_removed" global
@@ -55,6 +56,8 @@ $__profc_no_profc = comdat nodeduplicate
 
 $__profc_no_func = comdat nodeduplicate
 
+$__profc_use_func = comdat nodeduplicate
+
 $__llvm_profile_filename = comdat any
 
 @__llvm_profile_raw_version = hidden constant i64 648518346341351434, comdat
@@ -65,119 +68,153 @@ $__llvm_profile_filename = comdat any
 @__profn_no_counter = private constant [10 x i8] c"no_counter"
 @__profn_no_profc = private constant [8 x i8] c"no_profc"
 @__profn_no_func = private constant [7 x i8] c"no_func"
+ at __profn_use_func = private constant [8 x i8] c"use_func"
 @__profc_main = private global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", comdat, align 8, !dbg !0
- at __profc_no_name = private global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", comdat, align 8, !dbg !19
- at __profc_no_cfg = private global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", comdat, align 8, !dbg !24
- at __profc_no_counter = private global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", comdat, align 8, !dbg !29
- at __profc_no_func = private global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", comdat, align 8, !dbg !39
+ at __profc_no_name = private global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", comdat, align 8, !dbg !22
+ at __profc_no_cfg = private global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", comdat, align 8, !dbg !28
+ at __profc_no_counter = private global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", comdat, align 8, !dbg !34
+ at __profc_no_func = private global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", comdat, align 8, !dbg !46
+ at __profc_use_func = private global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", comdat, align 8, !dbg !52
 @llvm.compiler.used = appending global [5 x ptr] [ptr @__profc_main, ptr @__profc_no_name, ptr @__profc_no_cfg, ptr @__profc_no_counter, ptr @__profc_no_func], section "llvm.metadata"
 @__llvm_profile_filename = hidden constant [20 x i8] c"default_%m.proflite\00", comdat
 
 ; Function Attrs: noinline nounwind optnone uwtable
 define dso_local i32 @main() #0 !dbg !2 {
-  %1 = alloca i32, align 4
-  %2 = load i64, ptr @__profc_main, align 8
-  %3 = add i64 %2, 1
-  store i64 %3, ptr @__profc_main, align 8
-  store i32 0, ptr %1, align 4
-  ret i32 0, !dbg !53
+entry:
+  %retval = alloca i32, align 4
+  %pgocount = load i64, ptr @__profc_main, align 8
+  %0 = add i64 %pgocount, 1
+  store i64 %0, ptr @__profc_main, align 8
+  store i32 0, ptr %retval, align 4
+  ret i32 0, !dbg !64
+}
+
+; Function Attrs: noinline nounwind optnone uwtable
+define dso_local void @no_name() #0 !dbg !24 {
+entry:
+  %pgocount = load i64, ptr @__profc_no_name, align 8, !dbg !66
+  %0 = add i64 %pgocount, 1, !dbg !66
+  store i64 %0, ptr @__profc_no_name, align 8, !dbg !66
+  ret void, !dbg !66
 }
 
 ; Function Attrs: noinline nounwind optnone uwtable
-define dso_local void @no_name() #0 !dbg !21 {
-  %1 = load i64, ptr @__profc_no_name, align 8, !dbg !55
-  %2 = add i64 %1, 1, !dbg !55
-  store i64 %2, ptr @__profc_no_name, align 8, !dbg !55
-  ret void, !dbg !55
+define dso_local void @no_cfg() #0 !dbg !30 {
+entry:
+  %pgocount = load i64, ptr @__profc_no_cfg, align 8, !dbg !67
+  %0 = add i64 %pgocount, 1, !dbg !67
+  store i64 %0, ptr @__profc_no_cfg, align 8, !dbg !67
+  ret void, !dbg !67
 }
 
 ; Function Attrs: noinline nounwind optnone uwtable
-define dso_local void @no_cfg() #0 !dbg !26 {
-  %1 = load i64, ptr @__profc_no_cfg, align 8, !dbg !56
-  %2 = add i64 %1, 1, !dbg !56
-  store i64 %2, ptr @__profc_no_cfg, align 8, !dbg !56
-  ret void, !dbg !56
+define dso_local void @no_counter() #0 !dbg !36 {
+entry:
+  %pgocount = load i64, ptr @__profc_no_counter, align 8, !dbg !68
+  %0 = add i64 %pgocount, 1, !dbg !68
+  store i64 %0, ptr @__profc_no_counter, align 8, !dbg !68
+  ret void, !dbg !68
 }
 
 ; Function Attrs: noinline nounwind optnone uwtable
-define dso_local void @no_counter() #0 !dbg !31 {
-  %1 = load i64, ptr @__profc_no_counter, align 8, !dbg !57
-  %2 = add i64 %1, 1, !dbg !57
-  store i64 %2, ptr @__profc_no_counter, align 8, !dbg !57
-  ret void, !dbg !57
+define dso_local void @no_profc() #0 !dbg !42 {
+entry:
+  ret void, !dbg !69
 }
 
 ; Function Attrs: noinline nounwind optnone uwtable
-define dso_local void @no_profc() #0 !dbg !36 {
-  ret void, !dbg !58
+define dso_local void @use_func() #0 !dbg !54 {
+entry:
+  %pgocount = load i64, ptr @__profc_use_func, align 8, !dbg !71
+  %0 = add i64 %pgocount, 1, !dbg !71
+  store i64 %0, ptr @__profc_use_func, align 8, !dbg !71
+  %pgocount.i = load i64, ptr @__profc_no_func, align 8, !dbg !72
+  %1 = add i64 %pgocount.i, 1, !dbg !72
+  store i64 %1, ptr @__profc_no_func, align 8, !dbg !72
+  ret void, !dbg !74
 }
 
 ; Function Attrs: nounwind
-declare void @llvm.instrprof.increment(ptr, i64, i32, i32) #1
+declare void @llvm.instrprof.increment(ptr, i64, i32, i32) #2
 
 attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
-attributes #1 = { nounwind }
+attributes #1 = { alwaysinline nounwind uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #2 = { nounwind }
 
 !llvm.dbg.cu = !{!7}
-!llvm.module.flags = !{!46, !47, !48, !49, !50, !51, !52}
+!llvm.module.flags = !{!58, !59, !60, !61, !62, !63}
 
 !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
-!1 = distinct !DIGlobalVariable(name: "__profc_main", scope: !2, file: !3, type: !14, isLocal: true, isDefinition: true, annotations: !44)
-!2 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 1, type: !4, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !7)
-!3 = !DIFile(filename: "a.c", directory: "/proc/self/cwd", checksumkind: CSK_MD5, checksum: "22eee0eada6e6964fca794aa5a0966d0")
+!1 = distinct !DIGlobalVariable(name: "__profc_main", scope: !2, file: !3, type: !9, isLocal: true, isDefinition: true, annotations: !10)
+!2 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 1, type: !4, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !8)
+!3 = !DIFile(filename: "a.c", directory: "/proc/self/cwd", checksumkind: CSK_MD5, checksum: "7bab6089d746f793d8c0c8d39f3a691c")
 !4 = !DISubroutineType(types: !5)
 !5 = !{!6}
 !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!7 = distinct !DICompileUnit(language: DW_LANG_C11, file: !3, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !8, splitDebugInlining: false, nameTableKind: None)
-!8 = !{!0, !9, !19, !24, !29, !34, !39}
-!9 = !DIGlobalVariableExpression(var: !10, expr: !DIExpression())
-!10 = distinct !DIGlobalVariable(name: "__profc_removed", scope: !11, file: !3, type: !14, isLocal: true, isDefinition: true, annotations: !15)
-!11 = distinct !DISubprogram(name: "removed", scope: !3, file: !3, line: 3, type: !12, scopeLine: 3, spFlags: DISPFlagDefinition, unit: !7)
-!12 = !DISubroutineType(types: !13)
-!13 = !{null}
-!14 = !DIBasicType(tag: DW_TAG_unspecified_type, name: "Profile Data Type")
-!15 = !{!16, !17, !18}
-!16 = !{!"Function Name", !"removed"}
-!17 = !{!"CFG Hash", i64 742261418966908927}
-!18 = !{!"Num Counters", i32 1}
-!19 = !DIGlobalVariableExpression(var: !20, expr: !DIExpression())
-!20 = distinct !DIGlobalVariable(name: "__profc_no_name", scope: !21, file: !3, type: !14, isLocal: true, isDefinition: true, annotations: !22)
-!21 = distinct !DISubprogram(name: "no_name", scope: !3, file: !3, line: 4, type: !12, scopeLine: 4, spFlags: DISPFlagDefinition, unit: !7)
-!22 = !{!17, !18}
-!23 = !{!"Function Name", !"no_name"}
-!24 = !DIGlobalVariableExpression(var: !25, expr: !DIExpression())
-!25 = distinct !DIGlobalVariable(name: "__profc_no_cfg", scope: !26, file: !3, type: !14, isLocal: true, isDefinition: true, annotations: !27)
-!26 = distinct !DISubprogram(name: "no_cfg", scope: !3, file: !3, line: 5, type: !12, scopeLine: 5, spFlags: DISPFlagDefinition, unit: !7)
-!27 = !{!28, !18}
-!28 = !{!"Function Name", !"no_cfg"}
-!29 = !DIGlobalVariableExpression(var: !30, expr: !DIExpression())
-!30 = distinct !DIGlobalVariable(name: "__profc_no_counter", scope: !31, file: !3, type: !14, isLocal: true, isDefinition: true, annotations: !32)
-!31 = distinct !DISubprogram(name: "no_counter", scope: !3, file: !3, line: 6, type: !12, scopeLine: 6, spFlags: DISPFlagDefinition, unit: !7)
-!32 = !{!33, !17}
-!33 = !{!"Function Name", !"no_counter"}
+!7 = distinct !DICompileUnit(language: DW_LANG_C11, file: !3, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!8 = !{!0}
+!9 = !DIBasicType(tag: DW_TAG_unspecified_type, name: "Profile Data Type")
+!10 = !{!11, !12, !13}
+!11 = !{!"Function Name", !"main"}
+!12 = !{!"CFG Hash", i64 742261418966908927}
+!13 = !{!"Num Counters", i32 1}
+!14 = !DIGlobalVariableExpression(var: !15, expr: !DIExpression())
+!15 = distinct !DIGlobalVariable(name: "__profc_removed", scope: !16, file: !3, type: !9, isLocal: true, isDefinition: true, annotations: !20)
+!16 = distinct !DISubprogram(name: "removed", scope: !3, file: !3, line: 3, type: !17, scopeLine: 3, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !19)
+!17 = !DISubroutineType(types: !18)
+!18 = !{null}
+!19 = !{!14}
+!20 = !{!21, !12, !13}
+!21 = !{!"Function Name", !"removed"}
+!22 = !DIGlobalVariableExpression(var: !23, expr: !DIExpression())
+!23 = distinct !DIGlobalVariable(name: "__profc_no_name", scope: !24, file: !3, type: !9, isLocal: true, isDefinition: true, annotations: !26)
+!24 = distinct !DISubprogram(name: "no_name", scope: !3, file: !3, line: 4, type: !17, scopeLine: 4, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !25)
+!25 = !{!22}
+!26 = !{!12, !13}
+!28 = !DIGlobalVariableExpression(var: !29, expr: !DIExpression())
+!29 = distinct !DIGlobalVariable(name: "__profc_no_cfg", scope: !30, file: !3, type: !9, isLocal: true, isDefinition: true, annotations: !32)
+!30 = distinct !DISubprogram(name: "no_cfg", scope: !3, file: !3, line: 5, type: !17, scopeLine: 5, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !31)
+!31 = !{!28}
+!32 = !{!33, !13}
+!33 = !{!"Function Name", !"no_cfg"}
 !34 = !DIGlobalVariableExpression(var: !35, expr: !DIExpression())
-!35 = distinct !DIGlobalVariable(name: "__profc_no_profc", scope: !36, file: !3, type: !14, isLocal: true, isDefinition: true, annotations: !37)
-!36 = distinct !DISubprogram(name: "no_profc", scope: !3, file: !3, line: 7, type: !12, scopeLine: 7, spFlags: DISPFlagDefinition, unit: !7)
-!37 = !{!38, !17, !18}
-!38 = !{!"Function Name", !"no_profc"}
-!39 = !DIGlobalVariableExpression(var: !40, expr: !DIExpression())
-!40 = distinct !DIGlobalVariable(name: "__profc_no_func", scope: !41, file: !3, type: !14, isLocal: true, isDefinition: true, annotations: !42)
-!41 = distinct !DISubprogram(name: "no_func", scope: !3, file: !3, line: 8, type: !12, scopeLine: 8, spFlags: DISPFlagDefinition, unit: !7)
-!42 = !{!43, !17, !18}
-!43 = !{!"Function Name", !"no_func"}
-!44 = !{!45, !17, !18}
-!45 = !{!"Function Name", !"main"}
-!46 = !{i32 7, !"Dwarf Version", i32 5}
-!47 = !{i32 2, !"Debug Info Version", i32 3}
-!48 = !{i32 1, !"wchar_size", i32 4}
-!49 = !{i32 8, !"PIC Level", i32 2}
-!50 = !{i32 7, !"PIE Level", i32 2}
-!51 = !{i32 7, !"uwtable", i32 2}
-!52 = !{i32 7, !"frame-pointer", i32 2}
-!53 = !DILocation(line: 1, column: 14, scope: !2)
-!54 = !DILocation(line: 3, column: 17, scope: !11)
-!55 = !DILocation(line: 4, column: 17, scope: !21)
-!56 = !DILocation(line: 5, column: 16, scope: !26)
-!57 = !DILocation(line: 6, column: 20, scope: !31)
-!58 = !DILocation(line: 7, column: 18, scope: !36)
-!59 = !DILocation(line: 8, column: 17, scope: !41)
+!35 = distinct !DIGlobalVariable(name: "__profc_no_counter", scope: !36, file: !3, type: !9, isLocal: true, isDefinition: true, annotations: !38)
+!36 = distinct !DISubprogram(name: "no_counter", scope: !3, file: !3, line: 6, type: !17, scopeLine: 6, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !37)
+!37 = !{!34}
+!38 = !{!39, !12}
+!39 = !{!"Function Name", !"no_counter"}
+!40 = !DIGlobalVariableExpression(var: !41, expr: !DIExpression())
+!41 = distinct !DIGlobalVariable(name: "__profc_no_profc", scope: !42, file: !3, type: !9, isLocal: true, isDefinition: true, annotations: !44)
+!42 = distinct !DISubprogram(name: "no_profc", scope: !3, file: !3, line: 7, type: !17, scopeLine: 7, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !43)
+!43 = !{!40}
+!44 = !{!45, !12, !13}
+!45 = !{!"Function Name", !"no_profc"}
+!46 = !DIGlobalVariableExpression(var: !47, expr: !DIExpression())
+!47 = distinct !DIGlobalVariable(name: "__profc_no_func", scope: !48, file: !3, type: !9, isLocal: true, isDefinition: true, annotations: !50)
+!48 = distinct !DISubprogram(name: "no_func", scope: !3, file: !3, line: 8, type: !17, scopeLine: 8, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !49)
+!49 = !{!46}
+!50 = !{!51, !12, !13}
+!51 = !{!"Function Name", !"no_func"}
+!52 = !DIGlobalVariableExpression(var: !53, expr: !DIExpression())
+!53 = distinct !DIGlobalVariable(name: "__profc_use_func", scope: !54, file: !3, type: !9, isLocal: true, isDefinition: true, annotations: !56)
+!54 = distinct !DISubprogram(name: "use_func", scope: !3, file: !3, line: 9, type: !17, scopeLine: 9, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !55)
+!55 = !{!52}
+!56 = !{!57, !12, !13}
+!57 = !{!"Function Name", !"use_func"}
+!58 = !{i32 7, !"Dwarf Version", i32 5}
+!59 = !{i32 2, !"Debug Info Version", i32 3}
+!60 = !{i32 8, !"PIC Level", i32 2}
+!61 = !{i32 7, !"PIE Level", i32 2}
+!62 = !{i32 7, !"uwtable", i32 2}
+!63 = !{i32 7, !"frame-pointer", i32 2}
+!64 = !DILocation(line: 1, column: 14, scope: !2)
+!65 = !DILocation(line: 3, column: 17, scope: !16)
+!66 = !DILocation(line: 4, column: 17, scope: !24)
+!67 = !DILocation(line: 5, column: 16, scope: !30)
+!68 = !DILocation(line: 6, column: 20, scope: !36)
+!69 = !DILocation(line: 7, column: 18, scope: !42)
+!70 = !DILocation(line: 8, column: 48, scope: !48)
+!71 = !DILocation(line: 9, column: 19, scope: !54)
+!72 = !DILocation(line: 8, column: 48, scope: !48, inlinedAt: !73)
+!73 = distinct !DILocation(line: 9, column: 19, scope: !54)
+!74 = !DILocation(line: 9, column: 30, scope: !54)

>From 62fcd330d64c4415a70889699b8b0ce56335d489 Mon Sep 17 00:00:00 2001
From: Vladislav Dzhidzhoev <vdzhidzhoev at accesssoftek.com>
Date: Tue, 31 Mar 2026 16:00:53 +0200
Subject: [PATCH 3/3] instrprof-debug-info-correlate-warnings.ll: remove
 unnecessary change

---
 .../profile/Linux/instrprof-debug-info-correlate-warnings.ll    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate-warnings.ll b/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate-warnings.ll
index 6e5542f164bb2..ecd076c811dcc 100644
--- a/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate-warnings.ll
+++ b/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate-warnings.ll
@@ -1,7 +1,7 @@
 ; RUN: split-file %s %t
 ; RUN: %clang %t/a.ll -o %t/a.out
-; RUN: llvm-profdata merge --debug-info=%t/a.out %t/a.proftext --max-debug-info-correlation-warnings=0 -o %t/a.profdata 2>&1 | FileCheck %s --implicit-check-not=warning --check-prefixes=CHECK,NOLIMIT
 ; RUN: llvm-profdata merge --debug-info=%t/a.out %t/a.proftext --max-debug-info-correlation-warnings=2 -o %t/a.profdata 2>&1 | FileCheck %s --implicit-check-not=warning --check-prefixes=CHECK,LIMIT
+; RUN: llvm-profdata merge --debug-info=%t/a.out %t/a.proftext --max-debug-info-correlation-warnings=0 -o %t/a.profdata 2>&1 | FileCheck %s --implicit-check-not=warning --check-prefixes=CHECK,NOLIMIT
 
 ; CHECK: warning: Incomplete DIE for function None:
 ; CHECK: warning: Incomplete DIE for function no_cfg: CFGHash=None



More information about the llvm-commits mailing list