diff --git a/llvm/include/llvm/IR/Value.h b/llvm/include/llvm/IR/Value.h --- a/llvm/include/llvm/IR/Value.h +++ b/llvm/include/llvm/IR/Value.h @@ -565,6 +565,9 @@ /// Return true if there is metadata referencing this value. bool isUsedByMetadata() const { return IsUsedByMD; } + // Return true if this value is only transitively referenced by metadata. + bool isTransitiveUsedByMetadataOnly() const; + protected: /// Get the current metadata attachments for the given kind, if any. /// diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1847,11 +1847,12 @@ if (TM.Options.EmitAddrsig) { // Emit address-significance attributes for all globals. OutStreamer->emitAddrsig(); - for (const GlobalValue &GV : M.global_values()) - if (!GV.use_empty() && !GV.isThreadLocal() && - !GV.hasDLLImportStorageClass() && !GV.getName().startswith("llvm.") && - !GV.hasAtLeastLocalUnnamedAddr()) + for (const GlobalValue &GV : M.global_values()) { + if (!GV.use_empty() && !GV.isTransitiveUsedByMetadataOnly() && + !GV.isThreadLocal() && !GV.hasDLLImportStorageClass() && + !GV.getName().startswith("llvm.") && !GV.hasAtLeastLocalUnnamedAddr()) OutStreamer->emitAddrsigSym(getSymbol(&GV)); + } } // Emit symbol partition specifications (ELF only). diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp --- a/llvm/lib/IR/Value.cpp +++ b/llvm/lib/IR/Value.cpp @@ -980,6 +980,27 @@ return Alloca->isSwiftError(); } +bool Value::isTransitiveUsedByMetadataOnly() const { + if (use_empty()) + return false; + llvm::SmallVector WorkList; + llvm::SmallPtrSet Visited; + WorkList.insert(WorkList.begin(), user_begin(), user_end()); + while (!WorkList.empty()) { + const User *U = WorkList.back(); + WorkList.pop_back(); + Visited.insert(U); + // If it is transitively used by a global value or a non-constant value, + // it's obviously not only used by metadata. + if (!isa(U) || isa(U)) + return false; + for (const User *UU : U->users()) + if (!Visited.count(UU)) + WorkList.push_back(UU); + } + return true; +} + //===----------------------------------------------------------------------===// // ValueHandleBase Class //===----------------------------------------------------------------------===// diff --git a/llvm/test/CodeGen/X86/addrsig.ll b/llvm/test/CodeGen/X86/addrsig.ll --- a/llvm/test/CodeGen/X86/addrsig.ll +++ b/llvm/test/CodeGen/X86/addrsig.ll @@ -19,9 +19,20 @@ %a2 = bitcast i32* @a2 to i8* %i1 = bitcast void()* @i1 to i8* %i2 = bitcast void()* @i2 to i8* + call void @llvm.dbg.value(metadata i8* bitcast (void()* @metadata_f1 to i8*), metadata !5, metadata !DIExpression()), !dbg !7 + call void @llvm.dbg.value(metadata i8* bitcast (void()* @metadata_f2 to i8*), metadata !5, metadata !DIExpression()), !dbg !7 + call void @f4(i8* bitcast (void()* @metadata_f2 to i8*)) unreachable } +declare void @f4(i8*) unnamed_addr + +; CHECK-NOT: .addrsig_sym metadata_f1 +declare void @metadata_f1() + +; CHECK: .addrsig_sym metadata_f2 +declare void @metadata_f2() + ; CHECK-NOT: .addrsig_sym f2 define internal void @f2() local_unnamed_addr { unreachable @@ -55,3 +66,17 @@ @i1 = ifunc void(), void()* @f1 ; CHECK-NOT: .addrsig_sym i2 @i2 = internal local_unnamed_addr ifunc void(), void()* @f2 + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, isOptimized: false, runtimeVersion: 0, emissionKind: NoDebug) +!1 = !DIFile(filename: "a", directory: "") +!2 = !{i32 2, !"Debug Info Version", i32 3} +!3 = distinct !DISubprogram(scope: null, isLocal: false, isDefinition: true, isOptimized: false, unit: !0) +!4 = !DILocation(line: 0, scope: !3) +!5 = !DILocalVariable(scope: !6) +!6 = distinct !DISubprogram(scope: null, isLocal: false, isDefinition: true, isOptimized: false, unit: !0) +!7 = !DILocation(line: 0, scope: !6, inlinedAt: !4)