| ## Check that BOLT handles correctly folding functions with --icf=safe |
| ## that can be referenced through a non control flow instruction when ICP optimization is enabled. |
| ## This tests also checks that destructors are folded. |
| |
| # REQUIRES: system-linux, asserts |
| # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o |
| # RUN: %clang %cflags %t1.o -o %t.exe -Wl,-q |
| # RUN: llvm-bolt --no-threads %t.exe --icf -debug-only=bolt-icf -o %t.bolt 2>&1 | FileCheck --check-prefix=ICFCHECK %s |
| # RUN: llvm-bolt --no-threads %t.exe --icf=safe -debug-only=bolt-icf -o %t.bolt 2>&1 | FileCheck --check-prefix=SAFEICFCHECK %s |
| |
| # ICFCHECK: ICF iteration 1 |
| # ICFCHECK-NEXT: folding Derived3Destructor into Derived2Destructor |
| # ICFCHECK-NEXT: folding Derived3Func into Derived2Func |
| |
| # SAFEICFCHECK: skipping function with reference taken Derived3Func |
| # SAFEICFCHECK-NEXT: ICF iteration 1 |
| # SAFEICFCHECK-NEXT: folding Derived3Destructor into Derived2Destructor |
| |
| |
| ## generate profile |
| ## clang++ -O2 -fprofile-generate=. main.cpp -c -o mainProf.o |
| ## PROF=test.profdata |
| ## clang++ -m64 -fprofile-use=$PROF \ |
| ## -mllvm -disable-icp=true -mllvm -print-after-all \ |
| ## -g0 -flto=thin -fwhole-program-vtables -fno-split-lto-unit -O2 \ |
| ## -fdebug-types-section \ |
| ## main.cpp -c -o mainProfLTO.bc |
| ## PASS='pgo-icall-prom' |
| ## clang++ -m64 -fprofile-use=$PROF \ |
| ## -O3 -Rpass=$PASS \ |
| ## -mllvm -print-before=$PASS \ |
| ## -mllvm -print-after=$PASS \ |
| ## -mllvm -filter-print-funcs=main \ |
| ## -mllvm -debug-only=$PASS \ |
| ## -x ir \ |
| ## mainProfLTO.bc -c -o mainProfFinal.o |
| |
| ## class Base { |
| ## public: |
| ## virtual int func(int a, int b) const = 0; |
| ## |
| ## virtual ~Base() {}; |
| ## }; |
| ## |
| ## class Derived2 : public Base { |
| ## int c = 5; |
| ## public: |
| ## __attribute__((noinline)) int func(int a, int b)const override { return a * (a - b) + this->c; } |
| ## |
| ## ~Derived2() {} |
| ## }; |
| ## |
| ## class Derived3 : public Base { |
| ## int c = 500; |
| ## public: |
| ## __attribute__((noinline)) int func(int a, int b) const override { return a * (a - b) + this->c; } |
| ## ~Derived3() {} |
| ## }; |
| ## |
| ## __attribute__((noinline)) Base *createType(int a) { |
| ## Base *base = nullptr; |
| ## if (a == 4) |
| ## base = new Derived2(); |
| ## else |
| ## base = new Derived3(); |
| ## return base; |
| ## } |
| ## |
| ## extern int returnFive(); |
| ## extern int returnFourOrFive(int val); |
| ## int main(int argc, char **argv) { |
| ## int sum = 0; |
| ## int a = returnFourOrFive(argc); |
| ## int b = returnFive(); |
| ## Base *ptr = createType(a); |
| ## Base *ptr2 = createType(b); |
| ## sum += ptr->func(b, a) + ptr2->func(b, a); |
| ## return 0; |
| ## } |
| ## clang++ -c helper.cpp -o helper.o |
| ## int FooVar = 1; |
| ## int BarVar = 2; |
| ## |
| ## int fooGlobalFuncHelper(int a, int b) { |
| ## return 5; |
| ## } |
| ## Manually modified to remove "extra" assembly. |
| .globl main |
| .type main,@function |
| main: |
| leaq Derived3Func(%rip), %rcx |
| callq Derived3Func |
| .size main, .-main |
| |
| .weak Derived2Func |
| .type Derived2Func,@function |
| Derived2Func: |
| imull %esi, %eax |
| retq |
| .size Derived2Func, .-Derived2Func |
| |
| .weak Derived2Destructor |
| .type Derived2Destructor,@function |
| Derived2Destructor: |
| jmp _ZdlPvm@PLT |
| .size Derived2Destructor, .-Derived2Destructor |
| |
| .weak Derived3Func |
| .type Derived3Func,@function |
| Derived3Func: |
| imull %esi, %eax |
| retq |
| .size Derived3Func, .-Derived3Func |
| |
| .weak _ZN4BaseD2Ev |
| .type _ZN4BaseD2Ev,@function |
| _ZN4BaseD2Ev: |
| retq |
| .size _ZN4BaseD2Ev, .-_ZN4BaseD2Ev |
| |
| .weak Derived3Destructor |
| .type Derived3Destructor,@function |
| Derived3Destructor: |
| jmp _ZdlPvm@PLT |
| .size Derived3Destructor, .-Derived3Destructor |
| |
| .type _ZTV8Derived2,@object |
| .section .data.rel.ro._ZTV8Derived2,"awG",@progbits,_ZTV8Derived2,comdat |
| .weak _ZTV8Derived2 |
| _ZTV8Derived2: |
| .quad 0 |
| .quad _ZTI8Derived2 |
| .quad Derived2Func |
| .quad _ZN4BaseD2Ev |
| .quad Derived2Destructor |
| .size _ZTV8Derived2, 40 |
| |
| .type _ZTV8Derived3,@object |
| .section .data.rel.ro._ZTV8Derived3,"awG",@progbits,_ZTV8Derived3,comdat |
| .weak _ZTV8Derived3 |
| _ZTV8Derived3: |
| .quad 0 |
| .quad _ZTI8Derived3 |
| .quad Derived3Func |
| .quad _ZN4BaseD2Ev |
| .quad Derived3Destructor |
| .size _ZTV8Derived3, 40 |