diff options
| -rw-r--r-- | llvm/lib/LTO/LTOBackend.cpp | 21 | ||||
| -rw-r--r-- | llvm/test/ThinLTO/X86/deadstrip.ll | 2 | ||||
| -rw-r--r-- | llvm/test/Transforms/PGOProfile/thinlto_samplepgo_icp_droppeddead.ll | 71 | ||||
| -rw-r--r-- | llvm/test/tools/gold/X86/global_with_section.ll | 6 | 
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()  | 

