tejohnson created this revision.
tejohnson added a reviewer: wmi.
Herald added subscribers: wenlei, arphaman, steven_wu, hiraditya, inglorion, 
Prazek.
tejohnson requested review of this revision.
Herald added projects: clang, LLVM.
Herald added a subscriber: cfe-commits.

Follow on to D42816 <https://reviews.llvm.org/D42816> which dropped 
declarations of dead symbols. With
this change we also drop declarations which were never defined in this
module, but which are also unused after dead symbols are removed. These
symbols may or may not be dead in their defining modules.

Removing the unused declarations will prevent indirect call promotion in
the ThinLTO Backend from adding a new reference to a symbol, which can
result in linker unsats if that symbol was in fact dead and therefore
removed in its defining module. This can happen when we compile with a
sample profile collected from one binary but used for another, which may
have profiled targets that aren't used in the new binary.

Some test changes occur as a result (for whole program devirtualization,
we end up with a cast if there is no declaration in the module, for ICP
tests we may need to add a direct call to keep the declaration around).


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D92673

Files:
  clang/test/CodeGen/thinlto-distributed-cfi-devirt.ll
  llvm/lib/LTO/LTOBackend.cpp
  llvm/test/LTO/Resolution/X86/load-sample-prof-icp.ll
  llvm/test/ThinLTO/X86/cfi-devirt.ll
  llvm/test/ThinLTO/X86/devirt-after-icp.ll
  llvm/test/ThinLTO/X86/index-const-prop-alias.ll
  llvm/test/ThinLTO/X86/index-const-prop-dead.ll

Index: llvm/test/ThinLTO/X86/index-const-prop-dead.ll
===================================================================
--- llvm/test/ThinLTO/X86/index-const-prop-dead.ll
+++ llvm/test/ThinLTO/X86/index-const-prop-dead.ll
@@ -4,9 +4,9 @@
 ; RUN:               %t1.bc -r=%t1.bc,main,plx -r=%t1.bc,foo,pl -r=%t1.bc,g, -o %t3
 ; RUN: llvm-dis %t3.2.3.import.bc -o - | FileCheck %s
 
-; Dead globals are converted to declarations by ThinLTO in dropDeadSymbols
-; If we try to internalize such we'll get a broken module. 
-; CHECK: @g = external global i32
+; Dead globals are converted to declarations by ThinLTO, and unused declarations
+; are removed, in dropDeadSymbols,
+; CHECK-NOT: @g
 
 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
Index: llvm/test/ThinLTO/X86/index-const-prop-alias.ll
===================================================================
--- llvm/test/ThinLTO/X86/index-const-prop-alias.ll
+++ llvm/test/ThinLTO/X86/index-const-prop-alias.ll
@@ -15,16 +15,13 @@
 ; RUN:               %t2.bc -r=%t2.bc,g,pl -r=%t2.bc,g.alias,plx -save-temps -o %t5
 ; RUN: llvm-dis %t5.1.3.import.bc -o - | FileCheck %s --check-prefix=PRESERVED
 
-; We currently don't support importing aliases
-; IMPORT:       @g.alias = external global i32
-; IMPORT-NEXT:  @g = internal global i32 42, align 4 #0
+; IMPORT:  @g = internal global i32 42, align 4 #0
 ; IMPORT:  attributes #0 = { "thinlto-internalize" }
 
 ; CODEGEN:      define dso_local i32 @main
 ; CODEGEN-NEXT:    ret i32 42
 
-; PRESERVED:      @g.alias = external global i32
-; PRESERVED-NEXT: @g = available_externally global i32 42, align 4
+; PRESERVED: @g = available_externally global i32 42, align 4
 
 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
Index: llvm/test/ThinLTO/X86/devirt-after-icp.ll
===================================================================
--- llvm/test/ThinLTO/X86/devirt-after-icp.ll
+++ llvm/test/ThinLTO/X86/devirt-after-icp.ll
@@ -120,7 +120,7 @@
   %8 = load i32 (%class.B*)*, i32 (%class.B*)** %vfn.i, align 8
 ; Call to bar() can be devirtualized to call to B::bar(), since it was
 ; inlined from B::foo() after ICP introduced the guarded promotion.
-; CHECK-IR: %call.i = tail call i32 @_ZN1B3barEv(%class.B* %3)
+; CHECK-IR: %call.i = tail call i32 bitcast (void ()* @_ZN1B3barEv to i32 (%class.B*)*)(%class.B* %3)
   %call.i = tail call i32 %8(%class.B* %5)
   br label %if.end.icp
 
Index: llvm/test/ThinLTO/X86/cfi-devirt.ll
===================================================================
--- llvm/test/ThinLTO/X86/cfi-devirt.ll
+++ llvm/test/ThinLTO/X86/cfi-devirt.ll
@@ -97,7 +97,7 @@
   %4 = bitcast i8* %3 to i32 (%struct.A*, i32)*
 
   ; Check that the call was devirtualized.
-  ; CHECK-IR: %call = tail call i32 @_ZN1A1nEi
+  ; CHECK-IR: %call = tail call i32 bitcast (void ()* @_ZN1A1nEi
   %call = tail call i32 %4(%struct.A* nonnull %obj, i32 %a)
   %vtable16 = load i8*, i8** %0
   %5 = tail call { i8*, i1 } @llvm.type.checked.load(i8* %vtable16, i32 0, metadata !"_ZTS1A")
Index: llvm/test/LTO/Resolution/X86/load-sample-prof-icp.ll
===================================================================
--- llvm/test/LTO/Resolution/X86/load-sample-prof-icp.ll
+++ llvm/test/LTO/Resolution/X86/load-sample-prof-icp.ll
@@ -23,6 +23,11 @@
   %3 = load void ()*, void ()** %2
   ; CHECK: call void @bar(),{{.*}}!prof
   call void %3(), !dbg !10
+  ; Call bar directly so we don't eliminate the unused declaration before ICP,
+  ; which will block it.
+  ; CHECK: if.end.icp:
+  ; CHECK-NEXT: call void @bar()
+  call void @bar()
   ret void
 }
 
Index: llvm/lib/LTO/LTOBackend.cpp
===================================================================
--- llvm/lib/LTO/LTOBackend.cpp
+++ llvm/lib/LTO/LTOBackend.cpp
@@ -543,20 +543,30 @@
 
 static void dropDeadSymbols(Module &Mod, const GVSummaryMapTy &DefinedGlobals,
                             const ModuleSummaryIndex &Index) {
-  std::vector<GlobalValue*> DeadGVs;
-  for (auto &GV : Mod.global_values())
-    if (GlobalValueSummary *GVS = DefinedGlobals.lookup(GV.getGUID()))
+  std::vector<GlobalValue *> Declarations;
+  for (auto &GV : Mod.global_values()) {
+    if (GlobalValueSummary *GVS = DefinedGlobals.lookup(GV.getGUID())) {
       if (!Index.isGlobalValueLive(GVS)) {
-        DeadGVs.push_back(&GV);
+        Declarations.push_back(&GV);
         convertToDeclaration(GV);
       }
+    } else if (GV.isDeclaration())
+      // Check if any pre-existing declarations are unused after dead
+      // definitions are removed.
+      Declarations.push_back(&GV);
+  }
 
-  // Now that all dead bodies have been dropped, delete the actual objects
-  // themselves when possible.
-  for (GlobalValue *GV : DeadGVs) {
+  // Now that all dead bodies have been dropped, delete the declarations
+  // themselves when possible. Note this is important to avoid introducing
+  // calls to these functions during indirect call promotion, e.g. when using a
+  // sample profile from a different binary or different version of the source,
+  // that may reference virtual functions not live in this binary.
+  for (GlobalValue *GV : Declarations) {
     GV->removeDeadConstantUsers();
-    // Might reference something defined in native object (i.e. dropped a
-    // non-prevailing IR def, but we need to keep the declaration).
+    // Might have a reference to something defined in native object
+    // (i.e. dropped a non-prevailing IR def), so we need to keep the
+    // declaration. In this case there is a definition somewhere, so
+    // keeping the declaration should not cause any issues.
     if (GV->use_empty())
       GV->eraseFromParent();
   }
Index: clang/test/CodeGen/thinlto-distributed-cfi-devirt.ll
===================================================================
--- clang/test/CodeGen/thinlto-distributed-cfi-devirt.ll
+++ clang/test/CodeGen/thinlto-distributed-cfi-devirt.ll
@@ -85,8 +85,8 @@
   %4 = bitcast i8* %3 to i32 (%struct.A*, i32)*
 
   ; Check that the call was devirtualized.
-  ; CHECK-IR: %call = tail call i32 @_ZN1A1nEi
-  ; SKIP-IR-NOT: %call = tail call i32 @_ZN1A1nEi
+  ; CHECK-IR: %call = tail call i32 bitcast (void ()* @_ZN1A1nEi
+  ; SKIP-IR-NOT: %call = tail call i32 {{.*}}@_ZN1A1nEi
   %call = tail call i32 %4(%struct.A* nonnull %obj, i32 %a)
   %vtable16 = load i8*, i8** %0
   %5 = tail call { i8*, i1 } @llvm.type.checked.load(i8* %vtable16, i32 0, metadata !"_ZTS1A")
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D92673: [ThinLTO] R... Teresa Johnson via Phabricator via cfe-commits

Reply via email to