1; This test checks if we can outline a singleton instance (i.e., an instance that 2; does not repeat) through two codegen rounds. The first round identifies a local 3; outlining instance within thin-two.ll, which is then encoded in the resulting 4; object file and merged into the codegen data summary. 5; The second round utilizes the merged codegen data to optimistically outline a 6; singleton instance in thin-one.ll. 7; Note that this global outlining creates a unique instance for each sequence 8; without directly sharing identical functions for correctness. 9; Actual code size reductions occur at link time through identical code folding. 10; When both thinlto and lto modules are compiled, the lto module is processed 11; independently, without relying on the merged codegen data. In this case, 12; the identical code sequences are directly replaced by a common outlined function. 13 14; RUN: split-file %s %t 15 16; Verify each outlining instance is singleton with the global outlining for thinlto. 17; They will be identical, which can be folded by the linker with ICF. 18; RUN: opt -module-summary %t/thin-one.ll -o %t/thin-one.bc 19; RUN: opt -module-summary %t/thin-two.ll -o %t/thin-two.bc 20; RUN: llvm-lto2 run %t/thin-one.bc %t/thin-two.bc -o %t/thinlto \ 21; RUN: -r %t/thin-one.bc,_f3,px -r %t/thin-one.bc,_g,x \ 22; RUN: -r %t/thin-two.bc,_f1,px -r %t/thin-two.bc,_f2,px -r %t/thin-two.bc,_g,x \ 23; RUN: -codegen-data-thinlto-two-rounds 24 25; thin-one.ll will have one outlining instance itself (matched in the global outlined hash tree) 26; RUN: llvm-objdump -d %t/thinlto.1 | FileCheck %s --check-prefix=THINLTO-1 27; THINLTO-1: _OUTLINED_FUNCTION{{.*}}>: 28; THINLTO-1-NEXT: mov 29; THINLTO-1-NEXT: mov 30; THINLTO-1-NEXT: b 31 32; thin-two.ll will have two respective outlining instances (matched in the global outlined hash tree) 33; RUN: llvm-objdump -d %t/thinlto.2 | FileCheck %s --check-prefix=THINLTO-2 34; THINLTO-2: _OUTLINED_FUNCTION{{.*}}>: 35; THINLTO-2-NEXT: mov 36; THINLTO-2-NEXT: mov 37; THINLTO-2-NEXT: b 38; THINLTO-2: _OUTLINED_FUNCTION{{.*}}>: 39; THINLTO-2-NEXT: mov 40; THINLTO-2-NEXT: mov 41; THINLTO-2-NEXT: b 42 43; Now add a lto module to the above thinlto modules. 44; Verify the lto module is optimized independent of the global outlining for thinlto. 45; RUN: opt %t/lto.ll -o %t/lto.bc 46; RUN: llvm-lto2 run %t/thin-one.bc %t/thin-two.bc %t/lto.bc -o %t/out \ 47; RUN: -r %t/thin-one.bc,_f3,px -r %t/thin-one.bc,_g,x \ 48; RUN: -r %t/thin-two.bc,_f1,px -r %t/thin-two.bc,_f2,px -r %t/thin-two.bc,_g,x \ 49; RUN: -r %t/lto.bc,_f4,px -r %t/lto.bc,_f5,px -r %t/lto.bc,_f6,px -r %t/lto.bc,_g,x \ 50; RUN: -codegen-data-thinlto-two-rounds 51 52; lto.ll will have one shared outlining instance within the lto module itself (no global outlining). 53; RUN: llvm-objdump -d %t/out.0 | FileCheck %s --check-prefix=LTO-0 54; LTO-0: _OUTLINED_FUNCTION{{.*}}>: 55; LTO-0-NEXT: mov 56; LTO-0-NEXT: b 57; LTO-0-NOT: _OUTLINED_FUNCTION{{.*}}>: 58 59; thin-one.ll will have one outlining instance (matched in the global outlined hash tree) 60; RUN: llvm-objdump -d %t/out.1 | FileCheck %s --check-prefix=THINLTO-1 61 62; thin-two.ll will have two outlining instances (matched in the global outlined hash tree) 63; RUN: llvm-objdump -d %t/out.2 | FileCheck %s --check-prefix=THINLTO-2 64 65;--- thin-one.ll 66target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" 67target triple = "arm64-apple-darwin" 68 69declare i32 @g(i32, i32, i32) 70define i32 @f3() minsize { 71 %1 = call i32 @g(i32 30, i32 1, i32 2); 72 ret i32 %1 73} 74 75;--- thin-two.ll 76target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" 77target triple = "arm64-apple-darwin" 78 79declare i32 @g(i32, i32, i32) 80define i32 @f1() minsize { 81 %1 = call i32 @g(i32 10, i32 1, i32 2); 82 ret i32 %1 83} 84define i32 @f2() minsize { 85 %1 = call i32 @g(i32 20, i32 1, i32 2); 86 ret i32 %1 87} 88 89;--- lto.ll 90target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" 91target triple = "arm64-apple-darwin" 92 93declare i32 @g(i32, i32, i32) 94define i32 @f4() minsize { 95 %1 = call i32 @g(i32 10, i32 30, i32 2); 96 ret i32 %1 97} 98define i32 @f5() minsize { 99 %1 = call i32 @g(i32 20, i32 40, i32 2); 100 ret i32 %1 101} 102define i32 @f6() minsize { 103 %1 = call i32 @g(i32 50, i32 60, i32 2); 104 ret i32 %1 105} 106