[CodeGen] don't emit addrsig symbol if it's used only by metadata
authorZequan Wu <zequanwu@google.com>
Thu, 29 Apr 2021 04:25:51 +0000 (21:25 -0700)
committerZequan Wu <zequanwu@google.com>
Thu, 29 Apr 2021 22:39:30 +0000 (15:39 -0700)
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
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
llvm/lib/IR/Value.cpp
llvm/test/CodeGen/X86/addrsig.ll

index 6bc406c..f6fd621 100644 (file)
@@ -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.
   ///
index 581b877..e491fe7 100644 (file)
@@ -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).
index 47a5be4..8d6918c 100644 (file)
@@ -980,6 +980,27 @@ bool Value::isSwiftError() const {
   return Alloca->isSwiftError();
 }
 
+bool Value::isTransitiveUsedByMetadataOnly() const {
+  if (use_empty())
+    return false;
+  llvm::SmallVector<const User *, 32> WorkList;
+  llvm::SmallPtrSet<const User *, 32> 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<Constant>(U) || isa<GlobalValue>(U))
+      return false;
+    for (const User *UU : U->users())
+      if (!Visited.count(UU))
+        WorkList.push_back(UU);
+  }
+  return true;
+}
+
 //===----------------------------------------------------------------------===//
 //                             ValueHandleBase Class
 //===----------------------------------------------------------------------===//
index 0ff8e99..957de7e 100644 (file)
@@ -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)