From cab48e2f0e00648ef0494ce114f4e00a3ded330f Mon Sep 17 00:00:00 2001 From: Zequan Wu Date: Wed, 28 Apr 2021 21:25:51 -0700 Subject: [PATCH] [CodeGen] don't emit addrsig symbol if it's used only by metadata Value only used by metadata can be removed from .addrsig table. This solves the undefined symbol error when enabling addrsig table on COFF LTO. Differential Revision: https://reviews.llvm.org/D101512 --- llvm/include/llvm/IR/Value.h | 3 +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 9 ++++---- llvm/lib/IR/Value.cpp | 21 ++++++++++++++++++ llvm/test/CodeGen/X86/addrsig.ll | 25 ++++++++++++++++++++++ 4 files changed, 54 insertions(+), 4 deletions(-) diff --git a/llvm/include/llvm/IR/Value.h b/llvm/include/llvm/IR/Value.h index 6bc406c8de83..f6fd621b0d4a 100644 --- a/llvm/include/llvm/IR/Value.h +++ b/llvm/include/llvm/IR/Value.h @@ -565,6 +565,9 @@ public: /// 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 index 581b877ed587..e491fe7f9f19 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1847,11 +1847,12 @@ bool AsmPrinter::doFinalization(Module &M) { 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 index 47a5be4e5d70..8d6918c59d52 100644 --- a/llvm/lib/IR/Value.cpp +++ b/llvm/lib/IR/Value.cpp @@ -980,6 +980,27 @@ bool Value::isSwiftError() const { 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 index 0ff8e99b287d..957de7ec2a64 100644 --- a/llvm/test/CodeGen/X86/addrsig.ll +++ b/llvm/test/CodeGen/X86/addrsig.ll @@ -19,9 +19,20 @@ define void @f1() { %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 @@ declare void @f3() unnamed_addr @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)