1; Require asserts for -debug-only 2; REQUIRES: asserts 3 4; RUN: opt -module-summary %s -o %t1.bc 5; RUN: opt -module-summary %p/Inputs/deadstrip.ll -o %t2.bc 6; RUN: llvm-lto -thinlto-action=thinlink -o %t.index.bc %t1.bc %t2.bc 7 8; RUN: llvm-lto -exported-symbol=_main -thinlto-action=internalize %t1.bc -thinlto-index=%t.index.bc -o - | llvm-dis -o - | FileCheck %s 9; RUN: llvm-lto -exported-symbol=_main -thinlto-action=internalize %t2.bc -thinlto-index=%t.index.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=CHECK2 10 11; RUN: llvm-lto -exported-symbol=_main -thinlto-action=run -stats %t1.bc %t2.bc 2>&1 | FileCheck %s --check-prefix=STATS 12; RUN: llvm-nm %t1.bc.thinlto.o | FileCheck %s --check-prefix=CHECK-NM 13 14; RUN: llvm-lto2 run %t1.bc %t2.bc -o %t.out -save-temps -stats \ 15; RUN: -r %t1.bc,_main,plx \ 16; RUN: -r %t1.bc,_bar,pl \ 17; RUN: -r %t1.bc,_dead_func,pl \ 18; RUN: -r %t1.bc,_baz,l \ 19; RUN: -r %t1.bc,_boo,l \ 20; RUN: -r %t1.bc,_live_available_externally_func,l \ 21; RUN: -r %t1.bc,_live_linkonce_odr_func,l \ 22; RUN: -r %t1.bc,_live_weak_odr_func,l \ 23; RUN: -r %t1.bc,_linkonceodralias,pl \ 24; RUN: -r %t1.bc,_linkonceodrfuncwithalias,l \ 25; RUN: -r %t1.bc,_linkonceodrfuncwithalias_caller,pl \ 26; RUN: -r %t2.bc,_baz,pl \ 27; RUN: -r %t2.bc,_boo,pl \ 28; RUN: -r %t2.bc,_dead_func,l \ 29; RUN: -r %t2.bc,_another_dead_func,pl \ 30; RUN: -r %t2.bc,_linkonceodrfuncwithalias,pl \ 31; RUN: -thinlto-threads=1 \ 32; RUN: -disable-thinlto-funcattrs=0 \ 33; RUN: -debug-only=function-import 2>&1 | FileCheck %s --check-prefix=DEBUG --check-prefix=STATS 34; RUN: llvm-dis < %t.out.1.3.import.bc | FileCheck %s --check-prefix=LTO2 35; RUN: llvm-dis < %t.out.2.3.import.bc | FileCheck %s --check-prefix=LTO2-CHECK2 36; RUN: llvm-nm %t.out.1 | FileCheck %s --check-prefix=CHECK2-NM 37 38; RUN: llvm-bcanalyzer -dump %t.out.index.bc | FileCheck %s --check-prefix=COMBINED 39; Live, NotEligibleForImport, dso_local, Internal 40; COMBINED-DAG: <COMBINED_PROFILE {{.*}} op2=119 41; Live, dso_local, Internal 42; COMBINED-DAG: <COMBINED_PROFILE {{.*}} op2=103 43; Live, Local, WeakODR 44; COMBINED-DAG: <COMBINED_PROFILE {{.*}} op2=101 45; Live, Local, LinkOnceODR 46; COMBINED-DAG: <COMBINED_PROFILE {{.*}} op2=99 47; Live, Local, AvailableExternally 48; COMBINED-DAG: <COMBINED_PROFILE {{.*}} op2=97 49; Live, Local, External 50; COMBINED-DAG: <COMBINED_PROFILE {{.*}} op2=96 51; COMBINED-DAG: <COMBINED_PROFILE {{.*}} op2=96 52; COMBINED-DAG: <COMBINED_PROFILE {{.*}} op2=96 53; Local, (Dead) 54; COMBINED-DAG: <COMBINED_PROFILE {{.*}} op2=64 55; COMBINED-DAG: <COMBINED_PROFILE {{.*}} op2=64 56; COMBINED-DAG: <COMBINED_PROFILE {{.*}} op2=64 57 58; Dead-stripping on the index allows to internalize these, 59; and limit the import of @baz thanks to early pruning. 60; CHECK-NOT: available_externally {{.*}} @baz() 61; CHECK: @llvm.global_ctors = 62; CHECK: define internal void @_GLOBAL__I_a() 63; CHECK: define internal void @bar() { 64; CHECK: define internal void @bar_internal() 65; CHECK: define internal void @dead_func() { 66; CHECK-NOT: available_externally {{.*}} @baz() 67; LTO2-NOT: available_externally {{.*}} @baz() 68; LTO2: @llvm.global_ctors = 69; LTO2: define internal void @_GLOBAL__I_a() 70; LTO2: define internal void @bar() [[ATTR:#[0-9]+]] { 71; LTO2: define internal void @bar_internal() 72; LTO2-NOT: @dead_func() 73; LTO2-NOT: available_externally {{.*}} @baz() 74 75; Make sure we didn't internalize @boo, which is reachable via 76; llvm.global_ctors 77; CHECK2: define void @boo() 78; LTO2-CHECK2: define dso_local void @boo() 79 80; Make sure we keep @linkonceodrfuncwithalias in Input/deadstrip.ll alive as it 81; is reachable from @main. 82; LTO2-CHECK2: define weak_odr dso_local void @linkonceodrfuncwithalias() [[ATTR:#[0-9]+]] { 83 84; We should have eventually removed @baz since it was internalized and unused 85; CHECK2-NM-NOT: _baz 86 87; The final binary should not contain any of the dead functions, 88; only main is expected because bar is expected to be inlined and stripped out. 89; CHECK-NM-NOT: bar 90; CHECK-NM-NOT: dead 91; CHECK-NM: T _main 92; CHECK-NM-NOT: bar 93; CHECK-NM-NOT: dead 94 95; DEBUG-DAG: Live root: 2412314959268824392 (llvm.global_ctors) 96; DEBUG-DAG: Live root: 15822663052811949562 (main) 97; DEBUG-DAG: Ignores Dead GUID: 7342339837106705152 (dead_func) 98; DEBUG-DAG: Ignores Dead GUID: 7546896869197086323 (baz) 99; DEBUG-DAG: Initialize import for 15611644523426561710 (boo) 100; DEBUG-DAG: Ignores Dead GUID: 2384416018110111308 (another_dead_func) 101 102; LTO2-DAG: attributes [[ATTR]] = { norecurse nounwind } 103 104; STATS: 3 function-import - Number of dead stripped symbols in index 105 106; Next test the case where Inputs/deadstrip.ll does not get a module index, 107; which will cause it to be handled by regular LTO in the new LTO API. 108; In that case there are uses of @dead_func in the regular LTO partition 109; and it shouldn't be internalized. 110; RUN: opt %p/Inputs/deadstrip.ll -o %t3.bc 111; RUN: llvm-lto2 run %t1.bc %t3.bc -o %t4.out -save-temps \ 112; RUN: -r %t1.bc,_main,plx \ 113; RUN: -r %t1.bc,_bar,pl \ 114; RUN: -r %t1.bc,_dead_func,pl \ 115; RUN: -r %t1.bc,_baz,l \ 116; RUN: -r %t1.bc,_boo,l \ 117; RUN: -r %t1.bc,_live_available_externally_func,l \ 118; RUN: -r %t1.bc,_live_linkonce_odr_func,l \ 119; RUN: -r %t1.bc,_live_weak_odr_func,l \ 120; RUN: -r %t1.bc,_linkonceodralias,pl \ 121; RUN: -r %t1.bc,_linkonceodrfuncwithalias,l \ 122; RUN: -r %t1.bc,_linkonceodrfuncwithalias_caller,pl \ 123; RUN: -r %t3.bc,_baz,pl \ 124; RUN: -r %t3.bc,_boo,pl \ 125; RUN: -r %t3.bc,_dead_func,l \ 126; RUN: -r %t3.bc,_another_dead_func,pl \ 127; RUN: -r %t3.bc,_linkonceodrfuncwithalias,pl 128; RUN: llvm-dis < %t4.out.1.3.import.bc | FileCheck %s --check-prefix=CHECK-NOTDEAD 129; RUN: llvm-nm %t4.out.0 | FileCheck %s --check-prefix=CHECK-NM-NOTDEAD 130 131; We can't internalize @dead_func because of the use in the regular LTO 132; partition. 133; CHECK-NOTDEAD: define dso_local void @dead_func() 134; We also can't eliminate @baz because it is in the regular LTO partition 135; and called from @dead_func. 136; CHECK-NM-NOTDEAD: T _baz 137 138target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" 139target triple = "x86_64-apple-macosx10.11.0" 140 141 142@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__I_a, ptr null }] 143 144declare void @baz() 145 146declare void @boo() 147 148define internal void @_GLOBAL__I_a() #1 section "__TEXT,__StaticInit,regular,pure_instructions" { 149entry: 150 call void @boo() 151 ret void 152} 153 154define void @bar() { 155 ret void 156} 157 158define internal void @bar_internal() { 159 ret void 160} 161 162define void @dead_func() { 163 call void @bar() 164 call void @baz() 165 call void @bar_internal() 166 ret void 167} 168 169 170define linkonce_odr void @live_linkonce_odr_func() { 171 ret void 172} 173 174define weak_odr void @live_weak_odr_func() { 175 ret void 176} 177 178define available_externally void @live_available_externally_func() { 179 ret void 180} 181 182; This alias will set its base object in this file (linkonceodrfuncwithalias) 183; alive. 184; We want to make sure the @linkonceodrfuncwithalias copy in Input/deadstrip.ll 185; is also scanned when computing reachability. 186@linkonceodralias = linkonce_odr alias void (), ptr @linkonceodrfuncwithalias 187 188define linkonce_odr void @linkonceodrfuncwithalias() { 189entry: 190 ret void 191} 192 193define void @linkonceodrfuncwithalias_caller() { 194entry: 195 call void @linkonceodrfuncwithalias() 196 ret void 197} 198 199 200define void @main() { 201 call void @bar() 202 call void @bar_internal() 203 call void @live_linkonce_odr_func() 204 call void @live_weak_odr_func() 205 call void @live_available_externally_func() 206 call void @linkonceodrfuncwithalias_caller() 207 call void @linkonceodralias() 208 ret void 209} 210