[llvm] [NVPTX] Fix for LTO dwarf emission when multiple CUs with a mix of DebugDirectivesOnly and NoDebug (PR #190371)
Daniel Donenfeld via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 6 12:17:37 PDT 2026
https://github.com/daniel-donenfeld updated https://github.com/llvm/llvm-project/pull/190371
>From 921bac6a378e94f832fdd2d8a8ff00b9dab735c7 Mon Sep 17 00:00:00 2001
From: Daniel Donenfeld <ddonenfeld at nvidia.com>
Date: Wed, 1 Apr 2026 13:32:54 +0000
Subject: [PATCH 1/2] Fix for LTO issue when multiple CU with mix of
DebugDirectivesOnly and NoDebug
---
llvm/include/llvm/IR/DebugInfoMetadata.h | 1 +
llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp | 6 ++-
llvm/test/DebugInfo/NVPTX/no-debug-loc.ll | 46 +++++++++++++++++++++++
3 files changed, 52 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/DebugInfo/NVPTX/no-debug-loc.ll
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 24619d44f6d3b..be90a40004426 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -2123,6 +2123,7 @@ class DICompileUnit : public DIScope {
DebugEmissionKind getEmissionKind() const {
return (DebugEmissionKind)EmissionKind;
}
+ bool isNoDebug() const { return EmissionKind == NoDebug; }
bool isDebugDirectivesOnly() const {
return EmissionKind == DebugDirectivesOnly;
}
diff --git a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp
index 573671de03ab9..8475bac36b116 100644
--- a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp
+++ b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp
@@ -377,7 +377,11 @@ void NVPTXAsmPrinter::emitFunctionEntryLabel() {
// Emit initial .loc debug directive for correct relocation symbol data.
if (const DISubprogram *SP = MF->getFunction().getSubprogram()) {
assert(SP->getUnit());
- if (!SP->getUnit()->isDebugDirectivesOnly())
+ // NoDebug and DebugDirectivesOnly do not require emitting the initial loc
+ // directive. NoDebug does not require any debug directives and the initial
+ // loc directive is not needed for DebugDirectivesOnly as it is redundant
+ // assuming this is a non-empty function.
+ if (!SP->getUnit()->isDebugDirectivesOnly() && !SP->getUnit()->isNoDebug())
emitInitialRawDwarfLocDirective(*MF);
}
}
diff --git a/llvm/test/DebugInfo/NVPTX/no-debug-loc.ll b/llvm/test/DebugInfo/NVPTX/no-debug-loc.ll
new file mode 100644
index 0000000000000..8b4a4039cac6e
--- /dev/null
+++ b/llvm/test/DebugInfo/NVPTX/no-debug-loc.ll
@@ -0,0 +1,46 @@
+; RUN: llc < %s -mtriple=nvptx64-nvidia-cuda | FileCheck %s
+; RUN: %if ptxas %{ llc < %s -mtriple=nvptx64-nvidia-cuda | %ptxas-verify %}
+
+;; When a module contains multiple CUs where one is DebugDirectiveOnly and
+;; the rest are NoDebug, we would attempt to emit dwarf directives for the
+;; NoDebug CUs leading to an assertion. This test verifies that we only emit
+;; dwarf directives for the DebugDirectiveOnly CU.
+
+define i32 @foo(i32 %a, i32 %b) !dbg !5 {
+
+; CHECK: .loc [[FILE:[0-9]+]] 26 0 // debug_directives_only.cu:26:0
+; CHECK-NOT: .loc [[FILE]] 26 0 // debug_directives_only.cu:26:0
+; CHECK: .loc [[FILE]] 40 22 // debug_directives_only.cu:40:22
+
+ %add = add i32 %b, %a, !dbg !8
+ ret i32 %add, !dbg !8
+}
+
+define i32 @bar(i32 %a, i32 %b) !dbg !40 {
+
+; CHECK-NOT: .loc
+
+ %add = add i32 %b, %a, !dbg !41
+ ret i32 %add, !dbg !41
+}
+
+; CHECK: .file [[FILE]] "/test/directory/debug_directives_only.cu"
+; CHECK-NOT: .file {{[0-9]*}} "/test/directory/no_debug.cu"
+
+!llvm.dbg.cu = !{!0, !2}
+!nvvm.annotations = !{}
+!llvm.module.flags = !{!4}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: DebugDirectivesOnly)
+!1 = !DIFile(filename: "debug_directives_only.cu", directory: "/test/directory/")
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: NoDebug)
+!3 = !DIFile(filename: "no_debug.cu", directory: "/test/directory/")
+!4 = !{i32 1, !"Debug Info Version", i32 3}
+!5 = distinct !DISubprogram(name: "kernel", linkageName: "foo", scope: !1, file: !1, line: 123, type: !6, scopeLine: 26, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
+!6 = !DISubroutineType(types: !7)
+!7 = !{}
+!8 = !DILocation(line: 40, column: 22, scope: !31)
+!31 = distinct !DILexicalBlock(scope: !5, file: !1, line: 3, column: 17)
+!40 = distinct !DISubprogram(name: "kernel", linkageName: "bar", scope: !3, file: !3, line: 234, type: !6, scopeLine: 26, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2)
+!41 = !DILocation(line: 40, column: 22, scope: !42)
+!42 = distinct !DILexicalBlock(scope: !40, file: !3, line: 6, column: 8)
>From f2445fa62813ae808872a9dba9582ba00515f810 Mon Sep 17 00:00:00 2001
From: Daniel Donenfeld <ddonenfeld at nvidia.com>
Date: Mon, 6 Apr 2026 19:16:20 +0000
Subject: [PATCH 2/2] Address PR feedback
---
llvm/include/llvm/IR/DebugInfoMetadata.h | 1 +
llvm/test/DebugInfo/NVPTX/no-debug-loc.ll | 8 ++++----
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index be90a40004426..4aefb9bf9910c 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -2123,6 +2123,7 @@ class DICompileUnit : public DIScope {
DebugEmissionKind getEmissionKind() const {
return (DebugEmissionKind)EmissionKind;
}
+ // Return true if this CU was compiled with debug info disabled
bool isNoDebug() const { return EmissionKind == NoDebug; }
bool isDebugDirectivesOnly() const {
return EmissionKind == DebugDirectivesOnly;
diff --git a/llvm/test/DebugInfo/NVPTX/no-debug-loc.ll b/llvm/test/DebugInfo/NVPTX/no-debug-loc.ll
index 8b4a4039cac6e..3de22b0bedccc 100644
--- a/llvm/test/DebugInfo/NVPTX/no-debug-loc.ll
+++ b/llvm/test/DebugInfo/NVPTX/no-debug-loc.ll
@@ -1,13 +1,13 @@
; RUN: llc < %s -mtriple=nvptx64-nvidia-cuda | FileCheck %s
; RUN: %if ptxas %{ llc < %s -mtriple=nvptx64-nvidia-cuda | %ptxas-verify %}
-;; When a module contains multiple CUs where one is DebugDirectiveOnly and
+;; When a module contains multiple CUs where one is DebugDirectivesOnly and
;; the rest are NoDebug, we would attempt to emit dwarf directives for the
;; NoDebug CUs leading to an assertion. This test verifies that we only emit
-;; dwarf directives for the DebugDirectiveOnly CU.
+;; dwarf directives for the DebugDirectivesOnly CU.
define i32 @foo(i32 %a, i32 %b) !dbg !5 {
-
+; CHECK-LABEL: foo
; CHECK: .loc [[FILE:[0-9]+]] 26 0 // debug_directives_only.cu:26:0
; CHECK-NOT: .loc [[FILE]] 26 0 // debug_directives_only.cu:26:0
; CHECK: .loc [[FILE]] 40 22 // debug_directives_only.cu:40:22
@@ -17,7 +17,7 @@ define i32 @foo(i32 %a, i32 %b) !dbg !5 {
}
define i32 @bar(i32 %a, i32 %b) !dbg !40 {
-
+; CHECK-LABEL: bar
; CHECK-NOT: .loc
%add = add i32 %b, %a, !dbg !41
More information about the llvm-commits
mailing list