1; "-debug-only" requires asserts. 2; REQUIRES: asserts 3; RUN: rm -rf %t && split-file %s %t && cd %t 4 5; Generate per-module summaries. 6; RUN: opt -module-summary main.ll -o main.bc 7; RUN: opt -module-summary lib.ll -o lib.bc 8 9; Generate the combined summary and distributed indices. 10 11; - For function import, set 'import-instr-limit' to 7 and fall back to import 12; function declarations. 13; - In main.ll, function 'main' calls 'small_func' and 'large_func'. Both callees 14; are defined in lib.ll. 'small_func' has two indirect callees, one is smaller 15; and the other one is larger. Both callees of 'small_func' are defined in lib.ll. 16; - Given the import limit, in main's combined summary, the import type of 'small_func' 17; and 'small_indirect_callee' will be 'definition', and the import type of 18; large* functions and their aliasees will be 'declaration'. 19; 20; The test will disassemble combined summaries and check the import type is 21; correct. Right now postlink optimizer pipeline doesn't do anything (e.g., 22; import the declaration or de-serialize summary attributes yet) so there is 23; nothing to test more than the summary content. 24; 25; TODO: Extend this test case to test IR once postlink optimizer makes use of 26; the import type for declarations. 27; 28; RUN: llvm-lto2 run \ 29; RUN: -debug-only=function-import \ 30; RUN: -import-instr-limit=7 \ 31; RUN: -import-instr-evolution-factor=1.0 \ 32; RUN: -import-declaration \ 33; RUN: -thinlto-distributed-indexes \ 34; RUN: -r=main.bc,main,px \ 35; RUN: -r=main.bc,small_func, \ 36; RUN: -r=main.bc,large_func, \ 37; RUN: -r=main.bc,read_write_global_vars, \ 38; RUN: -r=main.bc,external_func, \ 39; RUN: -r=lib.bc,callee,pl \ 40; RUN: -r=lib.bc,large_indirect_callee,px \ 41; RUN: -r=lib.bc,large_indirect_bar,px \ 42; RUN: -r=lib.bc,small_func,px \ 43; RUN: -r=lib.bc,large_func,px \ 44; RUN: -r=lib.bc,read_write_global_vars,px \ 45; RUN: -r=lib.bc,large_indirect_callee_alias,px \ 46; RUN: -r=lib.bc,large_indirect_bar_alias,px \ 47; RUN: -r=lib.bc,calleeAddrs,px -r=lib.bc,calleeAddrs2,px -o summary main.bc lib.bc 2>&1 | FileCheck %s --check-prefix=DUMP 48; 49; RUN: llvm-lto -thinlto-action=thinlink -import-declaration -import-instr-limit=7 -import-instr-evolution-factor=1.0 -o combined.index.bc main.bc lib.bc 50; RUN: llvm-lto -thinlto-action=distributedindexes -debug-only=function-import -import-declaration -import-instr-limit=7 -import-instr-evolution-factor=1.0 -thinlto-index combined.index.bc main.bc lib.bc 2>&1 | FileCheck %s --check-prefix=DUMP 51 52; DUMP: - 2 function definitions and 4 function declarations imported from lib.bc 53 54; First disassemble per-module summary and find out the GUID for {large_func, large_indirect_callee}. 55; 56; RUN: llvm-dis lib.bc -o - | FileCheck %s --check-prefix=LIB-DIS 57; LIB-DIS: module: (path: "lib.bc", hash: (0, 0, 0, 0, 0)) 58; LIB-DIS: gv: (name: "large_func", summaries: {{.*}}) ; guid = 2418497564662708935 59; LIB-DIS: gv: (name: "large_indirect_bar_alias", summaries: {{.*}}, aliasee: [[LARGEINDIRECT_BAR:\^[0-9]+]]{{.*}}guid = 13590951773474913315 60; LIB-DIS: [[LARGEINDIRECT_BAR]] = gv: (name: "large_indirect_bar", summaries: {{.*}}) ; guid = 13770917885399536773 61; LIB-DIS: [[LARGEINDIRECT:\^[0-9]+]] = gv: (name: "large_indirect_callee", summaries: {{.*}}) ; guid = 14343440786664691134 62; LIB-DIS: gv: (name: "large_indirect_callee_alias", summaries: {{.*}}, aliasee: [[LARGEINDIRECT]]{{.*}}guid = 16730173943625350469 63; 64; Secondly disassemble main's combined summary and verify the import type of 65; these two GUIDs are declaration. 66; 67; RUN: llvm-dis main.bc.thinlto.bc -o - | FileCheck %s --check-prefix=MAIN-DIS 68; 69; MAIN-DIS: [[LIBMOD:\^[0-9]+]] = module: (path: "lib.bc", hash: (0, 0, 0, 0, 0)) 70; MAIN-DIS: gv: (guid: 2418497564662708935, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), insts: 8, {{.*}}))) 71; When alias is imported as a copy of the aliasee, but the aliasee is not being 72; imported by itself, the aliasee should be null. 73; MAIN-DIS: gv: (guid: 13590951773474913315, summaries: (alias: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), aliasee: null))) 74; MAIN-DIS: [[LARGEINDIRECT:\^[0-9]+]] = gv: (guid: 14343440786664691134, summaries: (function: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), insts: 8, {{.*}}))) 75; MAIN-DIS: gv: (guid: 16730173943625350469, summaries: (alias: (module: [[LIBMOD]], flags: ({{.*}} importType: declaration), aliasee: [[LARGEINDIRECT]]))) 76 77; RUN: opt -passes=function-import -import-all-index -summary-file=main.bc.thinlto.bc main.bc -o main-after-import.bc 78; RUN: llvm-dis -o - main-after-import.bc | FileCheck %s --check-prefix=MAIN-IMPORT 79 80; Tests that dso_local attribute is applied on a global var from its summary. 81MAIN-IMPORT: @read_write_global_vars = external dso_local global [1 x ptr] 82 83; Run in-process ThinLTO and tests that 84; 1. `callee` remains internalized even if the symbols of its callers 85; (large_func, large_indirect_callee, large_indirect_bar) are exported as 86; declarations and visible to main module. 87; 2. the debugging logs from `function-import` pass are expected. 88; Set relocation model to static so the dso_local attribute from a summary is 89; applied on the global variable declaration. 90 91; RUN: llvm-lto2 run \ 92; RUN: -relocation-model=static \ 93; RUN: -debug-only=function-import \ 94; RUN: -save-temps \ 95; RUN: -thinlto-threads=1 \ 96; RUN: -import-instr-limit=7 \ 97; RUN: -import-instr-evolution-factor=1.0 \ 98; RUN: -import-declaration \ 99; RUN: -r=main.bc,main,px \ 100; RUN: -r=main.bc,small_func, \ 101; RUN: -r=main.bc,large_func, \ 102; RUN: -r=main.bc,read_write_global_vars, \ 103; RUN: -r=main.bc,external_func, \ 104; RUN: -r=lib.bc,callee,pl \ 105; RUN: -r=lib.bc,large_indirect_callee,px \ 106; RUN: -r=lib.bc,large_indirect_bar,px \ 107; RUN: -r=lib.bc,small_func,px \ 108; RUN: -r=lib.bc,large_func,px \ 109; RUN: -r=lib.bc,read_write_global_vars,px \ 110; RUN: -r=lib.bc,large_indirect_callee_alias,px \ 111; RUN: -r=lib.bc,large_indirect_bar_alias,px \ 112; RUN: -r=lib.bc,calleeAddrs,px -r=lib.bc,calleeAddrs2,px -o in-process main.bc lib.bc 2>&1 | FileCheck %s --check-prefix=IMPORTDUMP 113 114; TODO: Extend this test case to test IR once postlink optimizer makes use of 115; the import type for declarations. 116; IMPORTDUMP-DAG: Not importing function 11825436545918268459 callee from lib.cc 117; IMPORTDUMP-DAG: Is importing function declaration 14343440786664691134 large_indirect_callee from lib.cc 118; IMPORTDUMP-DAG: Is importing function definition 13568239288960714650 small_indirect_callee from lib.cc 119; IMPORTDUMP-DAG: Is importing function definition 6976996067367342685 small_func from lib.cc 120; IMPORTDUMP-DAG: Is importing function declaration 2418497564662708935 large_func from lib.cc 121; IMPORTDUMP-DAG: Is importing global declaration 7680325410415171624 calleeAddrs from lib.cc 122; IMPORTDUMP-DAG: Is importing alias declaration 16730173943625350469 large_indirect_callee_alias from lib.cc 123; IMPORTDUMP-DAG: Is importing alias declaration 13590951773474913315 large_indirect_bar_alias from lib.cc 124; IMPORTDUMP-DAG: Not importing function 13770917885399536773 large_indirect_bar 125 126; RUN: llvm-dis in-process.1.3.import.bc -o - | FileCheck %s --check-prefix=IMPORT 127 128; RUN: llvm-dis in-process.2.2.internalize.bc -o - | FileCheck %s --check-prefix=INTERNALIZE 129 130; IMPORT-DAG: define available_externally void @small_func 131; IMPORT-DAG: define available_externally hidden void @small_indirect_callee 132; IMPORT-DAG: declare void @large_func 133; Tests that dso_local attribute is applied on a global var from its summary. 134; IMPORT-DAG: @read_write_global_vars = external dso_local global [1 x ptr] 135; IMPORT-NOT: large_indirect_callee 136; IMPORT-NOT: large_indirect_callee_alias 137; IMPORT-NOT: large_indirect_bar 138; IMPORT-NOT: large_indirect_bar_alias 139 140; INTERNALIZE: define internal void @callee() 141 142;--- main.ll 143target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" 144target triple = "x86_64-unknown-linux-gnu" 145 146@read_write_global_vars = external global [1 x ptr] 147 148define i32 @main() { 149 call void @small_func() 150 call void @large_func() 151 %num = call ptr @external_func(ptr @read_write_global_vars) 152 store ptr %num, ptr getelementptr inbounds ([1 x ptr], ptr @read_write_global_vars, i64 0, i64 0) 153 %res1 = call i32 @external_func(ptr @read_write_global_vars) 154 ret i32 0 155} 156 157declare void @small_func() 158 159; large_func without attributes 160declare void @large_func() 161 162declare ptr @external_func(ptr) 163 164;--- lib.ll 165source_filename = "lib.cc" 166target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" 167target triple = "x86_64-unknown-linux-gnu" 168 169; Both large_indirect_callee and large_indirect_callee_alias are referenced 170; and visible to main.ll. 171@calleeAddrs = global [3 x ptr] [ptr @large_indirect_callee, ptr @small_indirect_callee, ptr @large_indirect_callee_alias] 172 173; large_indirect_bar_alias is visible to main.ll but its aliasee isn't. 174@calleeAddrs2 = global [1 x ptr] [ptr @large_indirect_bar_alias] 175 176; @read_write_global_vars is not read-only nor write-only (in main.ll). It's not 177; a constant global var and has references, so it's not importable as a definition. 178@read_write_global_vars = dso_local global [1 x ptr] [ptr @large_indirect_callee] 179 180define void @callee() #1 { 181 ret void 182} 183 184define void @large_indirect_callee()#2 { 185 call void @callee() 186 call void @callee() 187 call void @callee() 188 call void @callee() 189 call void @callee() 190 call void @callee() 191 call void @callee() 192 ret void 193} 194 195define void @large_indirect_bar()#2 { 196 call void @callee() 197 call void @callee() 198 call void @callee() 199 call void @callee() 200 call void @callee() 201 call void @callee() 202 call void @callee() 203 ret void 204} 205 206define internal void @small_indirect_callee() #0 { 207entry: 208 %0 = load ptr, ptr @calleeAddrs2 209 call void %0(), !prof !3 210 ret void 211} 212 213@large_indirect_callee_alias = alias void(), ptr @large_indirect_callee 214 215@large_indirect_bar_alias = alias void(), ptr @large_indirect_bar 216 217define void @small_func() { 218entry: 219 %0 = load ptr, ptr @calleeAddrs 220 call void %0(), !prof !0 221 %1 = load ptr, ptr getelementptr inbounds ([3 x ptr], ptr @calleeAddrs, i64 0, i64 1) 222 call void %1(), !prof !1 223 %2 = load ptr, ptr getelementptr inbounds ([3 x ptr], ptr @calleeAddrs, i64 0, i64 2) 224 call void %2(), !prof !2 225 ret void 226} 227 228define void @large_func() #0 { 229entry: 230 call void @callee() 231 call void @callee() 232 call void @callee() 233 call void @callee() 234 call void @callee() 235 call void @callee() 236 call void @callee() 237 ret void 238} 239 240attributes #0 = { nounwind norecurse } 241 242attributes #1 = { noinline } 243 244attributes #2 = { norecurse } 245 246!0 = !{!"VP", i32 0, i64 1, i64 14343440786664691134, i64 1} 247!1 = !{!"VP", i32 0, i64 1, i64 13568239288960714650, i64 1} 248!2 = !{!"VP", i32 0, i64 1, i64 16730173943625350469, i64 1} 249!3 = !{!"VP", i32 0, i64 1, i64 13590951773474913315, i64 1} 250