| ; This test verifies whether we can outline a singleton instance (i.e., an instance that does not repeat) |
| ; by running two codegen rounds. |
| ; This test also verifies if caches for the two-round codegens are correctly working. |
| |
| ; REQUIRES: asserts |
| ; RUN: rm -rf %t |
| ; RUN: split-file %s %t |
| |
| ; 0. Base case without a cache. |
| ; Verify each outlining instance is singleton with the global outlining for thinlto. |
| ; They will be identical, which can be folded by the linker with ICF. |
| ; RUN: opt -module-hash -module-summary %t/thin-one.ll -o %t/thin-one.bc |
| ; RUN: opt -module-hash -module-summary %t/thin-two.ll -o %t/thin-two.bc |
| ; RUN: llvm-lto2 run %t/thin-one.bc %t/thin-two.bc -o %t/thinlto \ |
| ; RUN: -r %t/thin-one.bc,_f3,px -r %t/thin-one.bc,_g,x \ |
| ; RUN: -r %t/thin-two.bc,_f1,px -r %t/thin-two.bc,_f2,px -r %t/thin-two.bc,_g,x \ |
| ; RUN: -codegen-data-thinlto-two-rounds |
| |
| ; thin-one.ll will have one outlining instance (matched in the global outlined hash tree) |
| ; RUN: llvm-objdump -d %t/thinlto.1 | FileCheck %s --check-prefix=THINLTO-1 |
| ; THINLTO-1: _OUTLINED_FUNCTION{{.*}}>: |
| ; THINLTO-1-NEXT: mov |
| ; THINLTO-1-NEXT: mov |
| ; THINLTO-1-NEXT: b |
| |
| ; thin-two.ll will have two outlining instances (matched in the global outlined hash tree) |
| ; RUN: llvm-objdump -d %t/thinlto.2 | FileCheck %s --check-prefix=THINLTO-2 |
| ; THINLTO-2: _OUTLINED_FUNCTION{{.*}}>: |
| ; THINLTO-2-NEXT: mov |
| ; THINLTO-2-NEXT: mov |
| ; THINLTO-2-NEXT: b |
| ; THINLTO-2: _OUTLINED_FUNCTION{{.*}}>: |
| ; THINLTO-2-NEXT: mov |
| ; THINLTO-2-NEXT: mov |
| ; THINLTO-2-NEXT: b |
| |
| ; 1. Run this with a cache for the first time. |
| ; RUN: rm -rf %t.cache |
| ; RUN: llvm-lto2 run %t/thin-one.bc %t/thin-two.bc -o %t/thinlto-cold \ |
| ; RUN: -r %t/thin-one.bc,_f3,px -r %t/thin-one.bc,_g,x \ |
| ; RUN: -r %t/thin-two.bc,_f1,px -r %t/thin-two.bc,_f2,px -r %t/thin-two.bc,_g,x \ |
| ; RUN: -codegen-data-thinlto-two-rounds -cache-dir %t.cache -debug-only=lto -thinlto-threads 1 > %t.log-cold.txt 2>&1 |
| ; RUN: cat %t.log-cold.txt | FileCheck %s --check-prefix=COLD |
| ; diff %t/thinlto.1 %t/thinlto-cold.1 |
| ; diff %t/thinlto.2 %t/thinlto-cold.2 |
| |
| ; COLD: [FirstRound] Cache Miss for {{.*}}thin-one.bc |
| ; COLD: [FirstRound] Cache Miss for {{.*}}thin-two.bc |
| ; COLD: [SecondRound] Cache Miss for {{.*}}thin-one.bc |
| ; COLD: [SecondRound] Cache Miss for {{.*}}thin-two.bc |
| |
| ; There are two input bitcode files and each one is operated with 3 caches: |
| ; CG/IR caches for the first round and the second round CG cache. |
| ; So the total number of files are 2 * 3 = 6. |
| ; RUN: ls %t.cache | count 6 |
| |
| ; 2. Without any changes, simply re-running it will hit the cache. |
| ; RUN: llvm-lto2 run %t/thin-one.bc %t/thin-two.bc -o %t/thinlto-warm \ |
| ; RUN: -r %t/thin-one.bc,_f3,px -r %t/thin-one.bc,_g,x \ |
| ; RUN: -r %t/thin-two.bc,_f1,px -r %t/thin-two.bc,_f2,px -r %t/thin-two.bc,_g,x \ |
| ; RUN: -codegen-data-thinlto-two-rounds -cache-dir %t.cache -debug-only=lto -thinlto-threads 1 > %t.log-warm.txt 2>&1 |
| ; RUN: cat %t.log-warm.txt | FileCheck %s --check-prefix=WARM |
| ; diff %t/thinlto.1 %t/thinlto-warm.1 |
| ; diff %t/thinlto.2 %t/thinlto-warm.2 |
| |
| ; WARM-NOT: Cache Miss |
| |
| ; 3. Assume thin-one.ll has been modified to thin-one-modified.ll. |
| ; The merged CG data remains unchanged as this modification does not affect the hash tree built from thin-two.bc. |
| ; Therefore, both the first and second round runs update only this module. |
| ; RUN: opt -module-hash -module-summary %t/thin-one-modified.ll -o %t/thin-one.bc |
| ; RUN: llvm-lto2 run %t/thin-one.bc %t/thin-two.bc -o %t/thinlto-warm-modified \ |
| ; RUN: -r %t/thin-one.bc,_f3,px -r %t/thin-one.bc,_g,x \ |
| ; RUN: -r %t/thin-two.bc,_f1,px -r %t/thin-two.bc,_f2,px -r %t/thin-two.bc,_g,x \ |
| ; RUN: -codegen-data-thinlto-two-rounds -cache-dir %t.cache -debug-only=lto -thinlto-threads 1 > %t.log-warm-modified.txt 2>&1 |
| ; RUN: cat %t.log-warm-modified.txt | FileCheck %s --check-prefix=WARM-MODIFIED |
| ; diff %t/thinlto.1 %t/thinlto-warm-modified.1 |
| ; diff %t/thinlto.2 %t/thinlto-warm-modified.2 |
| |
| ; WARM-MODIFIED: [FirstRound] Cache Miss for {{.*}}thin-one.bc |
| ; WARM-MODIFIED-NOT: [FirstRound] Cache Miss for {{.*}}thin-two.bc |
| ; WARM-MODIFIED: [SecondRound] Cache Miss for {{.*}}thin-one.bc |
| ; WARM-MODIFIED-NOT: [SecondRound] Cache Miss for {{.*}}thin-two.bc |
| |
| ; 4. Additionally, thin-two.ll has been modified to thin-two-modified.ll. |
| ; In this case, the merged CG data, which is global, is updated. |
| ; Although the first round run updates only the thin-two.bc module, |
| ; as the module thin-one.bc remains the same as in step 3 above, |
| ; the second round run will update all modules, resulting in different binaries. |
| ; RUN: opt -module-hash -module-summary %t/thin-one-modified.ll -o %t/thin-one.bc |
| ; RUN: opt -module-hash -module-summary %t/thin-two-modified.ll -o %t/thin-two.bc |
| ; RUN: llvm-lto2 run %t/thin-one.bc %t/thin-two.bc -o %t/thinlto-warm-modified-all \ |
| ; RUN: -r %t/thin-one.bc,_f3,px -r %t/thin-one.bc,_g,x \ |
| ; RUN: -r %t/thin-two.bc,_f1,px -r %t/thin-two.bc,_f2,px -r %t/thin-two.bc,_g,x \ |
| ; RUN: -codegen-data-thinlto-two-rounds -cache-dir %t.cache -debug-only=lto -thinlto-threads 1 > %t.log-warm-modified-all.txt 2>&1 |
| ; RUN: cat %t.log-warm-modified-all.txt | FileCheck %s --check-prefix=WARM-MODIFIED-ALL |
| ; RUN: not diff %t/thinlto.1 %t/thinlto-warm-modified-all.1 |
| ; RUN: not diff %t/thinlto.2 %t/thinlto-warm-modified-all.2 |
| |
| ; WARM-MODIFIED-ALL-NOT: [FirstRound] Cache Miss for {{.*}}thin-one.bc |
| ; WARM-MODIFIED-ALL: [FirstRound] Cache Miss for {{.*}}thin-two.bc |
| ; WARM-MODIFIED-ALL: [SecondRound] Cache Miss for {{.*}}thin-one.bc |
| ; WARM-MODIFIED-ALL: [SecondRound] Cache Miss for {{.*}}thin-two.bc |
| |
| ; thin-one-modified.ll won't be outlined. |
| ; RUN: llvm-objdump -d %t/thinlto-warm-modified-all.1 | FileCheck %s --check-prefix=THINLTO-1-MODIFIED-ALL |
| ; THINLTO-1-MODIFIED-ALL-NOT: _OUTLINED_FUNCTION{{.*}}>: |
| |
| ; thin-two-modified.ll will have two (longer) outlining instances (matched in the global outlined hash tree) |
| ; RUN: llvm-objdump -d %t/thinlto-warm-modified-all.2| FileCheck %s --check-prefix=THINLTO-2-MODIFIED-ALL |
| ; THINLTO-2-MODIFIED-ALL: _OUTLINED_FUNCTION{{.*}}>: |
| ; THINLTO-2-MODIFIED-ALL: mov |
| ; THINLTO-2-MODIFIED-ALL: mov |
| ; THINLTO-2-MODIFIED-ALL: mov |
| ; THINLTO-2-MODIFIED-ALL: b |
| ; THINLTO-2-MODIFIED-ALL: _OUTLINED_FUNCTION{{.*}}>: |
| ; THINLTO-2-MODIFIED-ALL: mov |
| ; THINLTO-2-MODIFIED-ALL: mov |
| ; THINLTO-2-MODIFIED-ALL: mov |
| ; THINLTO-2-MODIFIED-ALL: b |
| |
| ; 5. Re-running it will hit the cache. |
| ; RUN: llvm-lto2 run %t/thin-one.bc %t/thin-two.bc -o %t/thinlto-warm-again \ |
| ; RUN: -r %t/thin-one.bc,_f3,px -r %t/thin-one.bc,_g,x \ |
| ; RUN: -r %t/thin-two.bc,_f1,px -r %t/thin-two.bc,_f2,px -r %t/thin-two.bc,_g,x \ |
| ; RUN: -codegen-data-thinlto-two-rounds -cache-dir %t.cache -debug-only=lto -thinlto-threads 1 > %t.log-warm-again.txt 2>&1 |
| ; RUN: cat %t.log-warm-again.txt | FileCheck %s --check-prefix=WARM-AGAIN |
| ; RUN: diff %t/thinlto-warm-modified-all.1 %t/thinlto-warm-again.1 |
| ; RUN: diff %t/thinlto-warm-modified-all.2 %t/thinlto-warm-again.2 |
| |
| ; WARM-AGAIN-NOT: Cache Miss |
| |
| ;--- thin-one.ll |
| target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" |
| target triple = "arm64-apple-darwin" |
| |
| declare i32 @g(i32, i32, i32) |
| define i32 @f3() minsize { |
| %1 = call i32 @g(i32 30, i32 1, i32 2); |
| ret i32 %1 |
| } |
| |
| ;--- thin-one-modified.ll |
| target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" |
| target triple = "arm64-apple-darwin" |
| |
| declare i32 @g(i32, i32, i32) |
| define i32 @f3() minsize { |
| %1 = call i32 @g(i32 31, i32 1, i32 2); |
| ret i32 %1 |
| } |
| |
| ;--- thin-two.ll |
| target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" |
| target triple = "arm64-apple-darwin" |
| |
| declare i32 @g(i32, i32, i32) |
| define i32 @f1() minsize { |
| %1 = call i32 @g(i32 10, i32 1, i32 2); |
| ret i32 %1 |
| } |
| define i32 @f2() minsize { |
| %1 = call i32 @g(i32 20, i32 1, i32 2); |
| ret i32 %1 |
| } |
| |
| ;--- thin-two-modified.ll |
| target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" |
| target triple = "arm64-apple-darwin" |
| |
| declare i32 @g(i32, i32, i32) |
| define i32 @f1() minsize { |
| %1 = call i32 @g(i32 10, i32 1, i32 2); |
| ret i32 %1 |
| } |
| define i32 @f2() minsize { |
| %1 = call i32 @g(i32 10, i32 1, i32 2); |
| ret i32 %1 |
| } |