summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/LTO/LTOBackend.cpp21
-rw-r--r--llvm/test/ThinLTO/X86/deadstrip.ll2
-rw-r--r--llvm/test/Transforms/PGOProfile/thinlto_samplepgo_icp_droppeddead.ll71
-rw-r--r--llvm/test/tools/gold/X86/global_with_section.ll6
4 files changed, 90 insertions, 10 deletions
diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index 49c0c2e15b3..4dbdd26be9d 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -401,14 +401,23 @@ Error lto::backend(Config &C, AddStreamFn AddStream,
static void dropDeadSymbols(Module &Mod, const GVSummaryMapTy &DefinedGlobals,
const ModuleSummaryIndex &Index) {
- std::vector<GlobalValue *> ReplacedGlobals;
+ std::vector<GlobalValue*> DeadGVs;
for (auto &GV : Mod.global_values())
if (GlobalValueSummary *GVS = DefinedGlobals.lookup(GV.getGUID()))
- if (!Index.isGlobalValueLive(GVS) && !convertToDeclaration(GV))
- ReplacedGlobals.push_back(&GV);
-
- for (GlobalValue *GV : ReplacedGlobals)
- GV->eraseFromParent();
+ if (!Index.isGlobalValueLive(GVS)) {
+ DeadGVs.push_back(&GV);
+ convertToDeclaration(GV);
+ }
+
+ // Now that all dead bodies have been dropped, delete the actual objects
+ // themselves when possible.
+ for (GlobalValue *GV : DeadGVs) {
+ GV->removeDeadConstantUsers();
+ // Might reference something defined in native object (i.e. dropped a
+ // non-prevailing IR def, but we need to keep the declaration).
+ if (GV->use_empty())
+ GV->eraseFromParent();
+ }
}
Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream,
diff --git a/llvm/test/ThinLTO/X86/deadstrip.ll b/llvm/test/ThinLTO/X86/deadstrip.ll
index f1a587359c8..e3f16a8e0b3 100644
--- a/llvm/test/ThinLTO/X86/deadstrip.ll
+++ b/llvm/test/ThinLTO/X86/deadstrip.ll
@@ -50,7 +50,7 @@
; LTO2: define internal void @_GLOBAL__I_a()
; LTO2: define internal void @bar() {
; LTO2: define internal void @bar_internal()
-; LTO2: declare dso_local void @dead_func()
+; LTO2-NOT: @dead_func()
; LTO2-NOT: available_externally {{.*}} @baz()
; Make sure we didn't internalize @boo, which is reachable via
diff --git a/llvm/test/Transforms/PGOProfile/thinlto_samplepgo_icp_droppeddead.ll b/llvm/test/Transforms/PGOProfile/thinlto_samplepgo_icp_droppeddead.ll
new file mode 100644
index 00000000000..fcbc2d64541
--- /dev/null
+++ b/llvm/test/Transforms/PGOProfile/thinlto_samplepgo_icp_droppeddead.ll
@@ -0,0 +1,71 @@
+; REQUIRES: x86-registered-target
+
+; RUN: opt -module-summary %s -o %t.bc
+
+; Tests that with dead stripping in the thin link enabled (default), we do not
+; promote to target of the dropped dead symbol _ZL3foov. This can happen with a
+; sample profile collected for one binary used to optimize for another binary.
+; RUN: llvm-lto2 run -save-temps -o %t2 %t.bc -r %t.bc,fptr,plx \
+; RUN: -r %t.bc,main,plx -r %t.bc,_ZL3foov,l
+; RUN: llvm-dis < %t2.1.4.opt.bc | FileCheck %s --check-prefix=OPT
+; RUN: llvm-lto2 run -save-temps -o %t2 %t.bc -r %t.bc,fptr,plx \
+; RUN: -r %t.bc,main,plx -r %t.bc,_ZL3foov,l -compute-dead=false
+; RUN: llvm-dis < %t2.1.4.opt.bc | FileCheck %s --check-prefix=OPT-NODEAD
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@fptr = local_unnamed_addr global void ()* null, align 8
+
+define void @_ZL3foov() #1 {
+entry:
+ ret void
+}
+
+define i32 @main() local_unnamed_addr #0 !prof !34 {
+entry:
+ %0 = load void ()*, void ()** @fptr, align 8
+; OPT-NOT: label %if.false.orig_indirect
+; OPT-NODEAD: br i1 %{{[0-9]+}}, label %if.end.icp, label %if.false.orig_indirect
+ tail call void %0(), !prof !40
+ ret i32 0
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3,!4}
+!llvm.ident = !{!31}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 5.0.0 (trunk 297016)", isOptimized: true, runtimeVersion: 0, emissionKind: NoDebug, enums: !2)
+!1 = !DIFile(filename: "main.cc", directory: ".")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"ProfileSummary", !5}
+!5 = !{!6, !7, !8, !9, !10, !11, !12, !13}
+!6 = !{!"ProfileFormat", !"SampleProfile"}
+!7 = !{!"TotalCount", i64 3003}
+!8 = !{!"MaxCount", i64 3000}
+!9 = !{!"MaxInternalCount", i64 0}
+!10 = !{!"MaxFunctionCount", i64 0}
+!11 = !{!"NumCounts", i64 3}
+!12 = !{!"NumFunctions", i64 1}
+!13 = !{!"DetailedSummary", !14}
+!14 = !{!15, !16, !17, !18, !19, !20, !20, !21, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30}
+!15 = !{i32 10000, i64 3000, i32 1}
+!16 = !{i32 100000, i64 3000, i32 1}
+!17 = !{i32 200000, i64 3000, i32 1}
+!18 = !{i32 300000, i64 3000, i32 1}
+!19 = !{i32 400000, i64 3000, i32 1}
+!20 = !{i32 500000, i64 3000, i32 1}
+!21 = !{i32 600000, i64 3000, i32 1}
+!22 = !{i32 700000, i64 3000, i32 1}
+!23 = !{i32 800000, i64 3000, i32 1}
+!24 = !{i32 900000, i64 3000, i32 1}
+!25 = !{i32 950000, i64 3000, i32 1}
+!26 = !{i32 990000, i64 3000, i32 1}
+!27 = !{i32 999000, i64 3000, i32 1}
+!28 = !{i32 999900, i64 2, i32 2}
+!29 = !{i32 999990, i64 2, i32 2}
+!30 = !{i32 999999, i64 2, i32 2}
+!31 = !{!"clang version 5.0.0 (trunk 297016)"}
+!34 = !{!"function_entry_count", i64 1}
+!40 = !{!"VP", i32 0, i64 3000, i64 -8789629626369651636, i64 3000}
diff --git a/llvm/test/tools/gold/X86/global_with_section.ll b/llvm/test/tools/gold/X86/global_with_section.ll
index 8ea4246c49c..2ba0a16e237 100644
--- a/llvm/test/tools/gold/X86/global_with_section.ll
+++ b/llvm/test/tools/gold/X86/global_with_section.ll
@@ -47,7 +47,7 @@ target triple = "x86_64-unknown-linux-gnu"
; the expected internalization.
; CHECK-REGULARLTO-DAG: @var_with_nonC_section = internal global i32 0, section ".nonCsection"
; Check we dropped definition of dead variable.
-; CHECK-THINLTO-DAG: @var_with_nonC_section = external dso_local global i32, section ".nonCsection"
+; CHECK-THINLTO-NOT: @var_with_nonC_section
@var_with_nonC_section = global i32 0, section ".nonCsection"
; We should not internalize @deadfunc_with_section due to section
@@ -61,7 +61,7 @@ define void @deadfunc_with_section() section "some_other_section" {
; the expected internalization.
; CHECK2-REGULARLTO-DAG: define internal void @deadfunc_with_nonC_section() section ".nonCsection"
; Check dead function converted to declaration.
-; CHECK-THINLTO-DAG: declare dso_local void @deadfunc_with_nonC_section() section ".nonCsection"
+; CHECK-THINLTO-NOT: @deadfunc_with_nonC_section()
define void @deadfunc_with_nonC_section() section ".nonCsection" {
call void @deadfunc2_called_from_nonC_section()
ret void
@@ -80,5 +80,5 @@ declare void @deadfunc2_called_from_section()
; are getting the expected internalization.
; CHECK2-REGULARLTO: define internal void @deadfunc2_called_from_nonC_section
; Check dead function converted to declaration.
-; CHECK2-THINLTO: declare dso_local void @deadfunc2_called_from_nonC_section
+; CHECK2-THINLTO-NOT: @deadfunc2_called_from_nonC_section
declare void @deadfunc2_called_from_nonC_section()
OpenPOWER on IntegriCloud