[llvm] c4de387 - [NVPTX] Fix for LTO dwarf emission when multiple CUs with a mix of DebugDirectivesOnly and NoDebug (#190371)
via llvm-commits
llvm-commits at lists.llvm.org
Mon May 4 18:15:36 PDT 2026
Author: Daniel Donenfeld
Date: 2026-05-04T18:15:30-07:00
New Revision: c4de38727ecb9538e6f0f82e5441410020e75bb0
URL: https://github.com/llvm/llvm-project/commit/c4de38727ecb9538e6f0f82e5441410020e75bb0
DIFF: https://github.com/llvm/llvm-project/commit/c4de38727ecb9538e6f0f82e5441410020e75bb0.diff
LOG: [NVPTX] Fix for LTO dwarf emission when multiple CUs with a mix of DebugDirectivesOnly and NoDebug (#190371)
Only emit the initial .loc dwarf directive if the CU requires debug
information. When a module contains multiple CUs where one is
DebugDirectiveOnly and the rest are NoDebug, we attempt to emit dwarf
for the NoDebug compile units leading to an assertion when calling
emitDwarfFile0Directive when in getOrCreateDwarfCompileUnit.
I added a lit test for this case which used to assert.
Added:
llvm/test/DebugInfo/NVPTX/no-debug-loc.ll
Modified:
llvm/include/llvm/CodeGen/AsmPrinter.h
llvm/include/llvm/IR/DebugInfoMetadata.h
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index ae09f2df3a47d..ff9d6d73ce146 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -360,9 +360,6 @@ class LLVM_ABI AsmPrinter : public MachineFunctionPass {
void EmitToStreamer(MCStreamer &S, const MCInst &Inst);
- /// Emits inital debug location directive.
- void emitInitialRawDwarfLocDirective(const MachineFunction &MF);
-
/// Return the current section we are emitting to.
const MCSection *getCurrentSection() const;
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 936029a33943d..8b16ffb2d7322 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -2156,6 +2156,8 @@ 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/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index ba66598de66c5..17fd80e81a673 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -506,19 +506,6 @@ void AsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
S.emitInstruction(Inst, getSubtargetInfo());
}
-void AsmPrinter::emitInitialRawDwarfLocDirective(const MachineFunction &MF) {
- if (DD) {
- assert(OutStreamer->hasRawTextSupport() &&
- "Expected assembly output mode.");
- // This is NVPTX specific and it's unclear why.
- // PR51079: If we have code without debug information we need to give up.
- DISubprogram *MFSP = MF.getFunction().getSubprogram();
- if (!MFSP)
- return;
- (void)DD->emitInitialLocDirective(MF, /*CUID=*/0);
- }
-}
-
/// getCurrentSection() - Return the current section we are emitting to.
const MCSection *AsmPrinter::getCurrentSection() const {
return OutStreamer->getCurrentSectionOnly();
diff --git a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp
index 8b243f635abb6..7d75cd8cebd6a 100644
--- a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp
+++ b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp
@@ -111,6 +111,30 @@ static StringRef getSamplerName(const Value &V) {
return V.getName();
}
+/// Emits initial debug location directive.
+static void emitInitialRawDwarfLocDirective(const MachineFunction &MF,
+ DwarfDebug *DD,
+ MCStreamer &OutStreamer) {
+ if (!DD)
+ return;
+
+ assert(OutStreamer.hasRawTextSupport() && "Expected assembly output mode.");
+ // This is NVPTX specific and it's unclear why.
+ // PR51079: If we have code without debug information we need to give up.
+ const DISubprogram *SP = MF.getFunction().getSubprogram();
+ if (!SP)
+ return;
+ assert(SP->getUnit());
+ // 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())
+ return;
+
+ (void)DD->emitInitialLocDirective(MF, /*CUID=*/0);
+}
+
/// discoverDependentGlobals - Return a set of GlobalVariables on which \p V
/// depends.
static void
@@ -375,11 +399,7 @@ void NVPTXAsmPrinter::emitFunctionEntryLabel() {
setAndEmitFunctionVirtualRegisters(*MF);
encodeDebugInfoRegisterNumbers(*MF);
// Emit initial .loc debug directive for correct relocation symbol data.
- if (const DISubprogram *SP = MF->getFunction().getSubprogram()) {
- assert(SP->getUnit());
- if (!SP->getUnit()->isDebugDirectivesOnly())
- emitInitialRawDwarfLocDirective(*MF);
- }
+ emitInitialRawDwarfLocDirective(*MF, getDwarfDebug(), *OutStreamer);
}
bool NVPTXAsmPrinter::runOnMachineFunction(MachineFunction &F) {
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..f49ba860f3e85
--- /dev/null
+++ b/llvm/test/DebugInfo/NVPTX/no-debug-loc.ll
@@ -0,0 +1,92 @@
+; RUN: split-file %s %t
+; RUN: llc < %t/debug-then-nodebug.ll -mtriple=nvptx64-nvidia-cuda | FileCheck %t/debug-then-nodebug.ll
+; RUN: llc < %t/nodebug-then-debug.ll -mtriple=nvptx64-nvidia-cuda | FileCheck %t/nodebug-then-debug.ll
+; RUN: %if ptxas %{ llc < %t/debug-then-nodebug.ll -mtriple=nvptx64-nvidia-cuda | %ptxas-verify %}
+; RUN: %if ptxas %{ llc < %t/nodebug-then-debug.ll -mtriple=nvptx64-nvidia-cuda | %ptxas-verify %}
+
+;; When a module contains multiple CUs where one is DebugDirectivesOnly and
+;; another is NoDebug, we would attempt to emit dwarf directives for the
+;; NoDebug CU leading to an assertion. This test verifies that we only emit
+;; dwarf directives for the DebugDirectivesOnly CU regardless of function order.
+
+;--- debug-then-nodebug.ll
+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
+
+ %add = add i32 %b, %a, !dbg !8
+ ret i32 %add, !dbg !8
+}
+
+define i32 @bar(i32 %a, i32 %b) !dbg !40 {
+; CHECK-LABEL: bar
+; 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"
+; CHECK-NOT: .section .debug{{.*}}
+
+!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)
+
+;--- nodebug-then-debug.ll
+define i32 @baz(i32 %a, i32 %b) !dbg !5 {
+; CHECK-LABEL: baz
+; CHECK-NOT: .loc
+
+ %add = add i32 %b, %a, !dbg !8
+ ret i32 %add, !dbg !8
+}
+
+define i32 @qux(i32 %a, i32 %b) !dbg !40 {
+; CHECK-LABEL: qux
+; 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 !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"
+; CHECK-NOT: .section .debug{{.*}}
+
+!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: NoDebug)
+!1 = !DIFile(filename: "no_debug.cu", directory: "/test/directory/")
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: DebugDirectivesOnly)
+!3 = !DIFile(filename: "debug_directives_only.cu", directory: "/test/directory/")
+!4 = !{i32 1, !"Debug Info Version", i32 3}
+!5 = distinct !DISubprogram(name: "kernel", linkageName: "baz", scope: !1, file: !1, line: 345, 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: 6, column: 8)
+!40 = distinct !DISubprogram(name: "kernel", linkageName: "qux", scope: !3, file: !3, line: 456, 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: 3, column: 17)
More information about the llvm-commits
mailing list