diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h --- a/llvm/include/llvm/LTO/LTO.h +++ b/llvm/include/llvm/LTO/LTO.h @@ -444,6 +444,9 @@ // Identify symbols exported dynamically, and that therefore could be // referenced by a shared library not visible to the linker. DenseSet DynamicExportSymbols; + + // Diagnostic optimization remarks file + std::unique_ptr DiagnosticOutputFile; }; /// The resolution for a symbol. The linker must provide a SymbolResolution for diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -857,10 +857,14 @@ for (GlobalValue *GV : Mod.Keep) { if (LivenessFromIndex && !ThinLTO.CombinedIndex.isGUIDLive(GV->getGUID())) { if (Function *F = dyn_cast(GV)) { - OptimizationRemarkEmitter ORE(F, nullptr); - ORE.emit(OptimizationRemark(DEBUG_TYPE, "deadfunction", F) - << ore::NV("Function", F) - << " not added to the combined module "); + if (DiagnosticOutputFile) { + if (Error Err = F->materialize()) + return Err; + OptimizationRemarkEmitter ORE(F, nullptr); + ORE.emit(OptimizationRemark(DEBUG_TYPE, "deadfunction", F) + << ore::NV("Function", F) + << " not added to the combined module "); + } } continue; } @@ -1049,6 +1053,7 @@ Conf.RemarksHotnessThreshold); if (!DiagFileOrErr) return DiagFileOrErr.takeError(); + DiagnosticOutputFile = std::move(*DiagFileOrErr); // Finalize linking of regular LTO modules containing summaries now that // we have computed liveness information. @@ -1137,7 +1142,7 @@ return Err; } - return finalizeOptimizationRemarks(std::move(*DiagFileOrErr)); + return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile)); } static const char *libcallRoutineNames[] = { diff --git a/llvm/test/LTO/Resolution/X86/dead-strip-fulllto.ll b/llvm/test/LTO/Resolution/X86/dead-strip-fulllto.ll --- a/llvm/test/LTO/Resolution/X86/dead-strip-fulllto.ll +++ b/llvm/test/LTO/Resolution/X86/dead-strip-fulllto.ll @@ -19,9 +19,11 @@ ; REMARK: Pass: lto ; REMARK-NEXT: Name: deadfunction +; REMARK-NEXT: DebugLoc: { File: test.c, Line: 4, Column: 0 } ; REMARK-NEXT: Function: dead2 ; REMARK-NEXT: Args: ; REMARK-NEXT: - Function: dead2 +; REMARK-NEXT: DebugLoc: { File: test.c, Line: 4, Column: 0 } ; REMARK-NEXT: - String: ' not added to the combined module ' ; FULL-NOT: dead @@ -48,9 +50,18 @@ ret void } -define void @dead2() { +define void @dead2() !dbg !7 { ret void } -!0 = !{i32 1, !"ThinLTO", i32 0} -!llvm.module.flags = !{ !0 } +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, isOptimized: false, emissionKind: LineTablesOnly, enums: !2) +!1 = !DIFile(filename: "test.c", directory: "/") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 2} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"ThinLTO", i32 0} +!7 = distinct !DISubprogram(name: "dead2", scope: !1, file: !1, line: 4, type: !8, isLocal: false, isDefinition: true, scopeLine: 4, isOptimized: false, unit: !0, retainedNodes: !2) +!8 = !DISubroutineType(types: !2)