diff options
| author | Piotr Padlewski <prazek@google.com> | 2015-08-17 23:33:49 +0000 |
|---|---|---|
| committer | Piotr Padlewski <prazek@google.com> | 2015-08-17 23:33:49 +0000 |
| commit | a3f6f9477b0781617102a0e62695fcd0ea5ca942 (patch) | |
| tree | 7499edb057479cf4f43ac5983bccdc11cb8bca56 /clang/test | |
| parent | 76b2a3ee9dfd87f946fc703958c15fb11ba9a6a0 (diff) | |
| download | bcm5719-llvm-a3f6f9477b0781617102a0e62695fcd0ea5ca942.tar.gz bcm5719-llvm-a3f6f9477b0781617102a0e62695fcd0ea5ca942.zip | |
Generating assumption loads of vptr after ctor call
Generating call assume(icmp %vtable, %global_vtable) after constructor
call for devirtualization purposes.
For more info go to:
http://lists.llvm.org/pipermail/cfe-dev/2015-July/044227.html
http://reviews.llvm.org/D11859
llvm-svn: 245257
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/CodeGen/available-externally-hidden.cpp | 2 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/ctor-globalopt.cpp | 4 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/template-instantiation.cpp | 3 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/thunks.cpp | 30 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/virtual-base-ctor.cpp | 2 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/vtable-assume-load.cpp | 173 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/vtable-available-externally.cpp | 14 |
7 files changed, 209 insertions, 19 deletions
diff --git a/clang/test/CodeGen/available-externally-hidden.cpp b/clang/test/CodeGen/available-externally-hidden.cpp index dc13f26b752..88ebfa9684a 100644 --- a/clang/test/CodeGen/available-externally-hidden.cpp +++ b/clang/test/CodeGen/available-externally-hidden.cpp @@ -27,6 +27,6 @@ class TestSyncMessageFilter : public SyncMessageFilter { }; int main() { -TestSyncMessageFilter* f = new TestSyncMessageFilter; + TestSyncMessageFilter *f = new TestSyncMessageFilter; f->Send(new Message); } diff --git a/clang/test/CodeGenCXX/ctor-globalopt.cpp b/clang/test/CodeGenCXX/ctor-globalopt.cpp index bcab60916ae..6fd2118acad 100644 --- a/clang/test/CodeGenCXX/ctor-globalopt.cpp +++ b/clang/test/CodeGenCXX/ctor-globalopt.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s -O1 | FileCheck %s --check-prefix=O1 +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -o - %s -O2 | opt - -S -globalopt -o - | FileCheck %s --check-prefix=O1 // RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s -O1 | FileCheck %s --check-prefix=O1 +// RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -o - %s -O2 | opt - -S -globalopt -o - | FileCheck %s --check-prefix=O1 // Check that GlobalOpt can eliminate static constructors for simple implicit // constructors. This is a targetted integration test to make sure that LLVM's diff --git a/clang/test/CodeGenCXX/template-instantiation.cpp b/clang/test/CodeGenCXX/template-instantiation.cpp index 90b8099f0a2..0eab85abeea 100644 --- a/clang/test/CodeGenCXX/template-instantiation.cpp +++ b/clang/test/CodeGenCXX/template-instantiation.cpp @@ -1,5 +1,7 @@ // RUN: %clang_cc1 %s -O1 -disable-llvm-optzns -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s +// CHECK: @_ZTVN5test018stdio_sync_filebufIA4_iEE = linkonce_odr unnamed_addr constant + // CHECK: @_ZN7PR100011xE = global // CHECK-NOT: @_ZN7PR100014kBarE = external global i32 // @@ -12,7 +14,6 @@ // CHECK: @_ZN7PR100011SIiE3arrE = linkonce_odr global [3 x i32] // CHECK-NOT: @_ZN7PR100011SIiE3arr2E = linkonce_odr global [3 x i32]A -// CHECK: @_ZTVN5test018stdio_sync_filebufIA4_iEE = linkonce_odr unnamed_addr constant // CHECK-NOT: _ZTVN5test31SIiEE // CHECK-NOT: _ZTSN5test31SIiEE diff --git a/clang/test/CodeGenCXX/thunks.cpp b/clang/test/CodeGenCXX/thunks.cpp index 38afb9d0dbf..3e5f0059b8f 100644 --- a/clang/test/CodeGenCXX/thunks.cpp +++ b/clang/test/CodeGenCXX/thunks.cpp @@ -1,5 +1,9 @@ -// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - -O1 -disable-llvm-optzns | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o %t +// RUN: %clang_cc1 %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o %t.opt -O1 -disable-llvm-optzns +// RUN: FileCheck %s < %t +// RUN: FileCheck %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-NONOPT %s < %t +// RUN: FileCheck --check-prefix=CHECK-OPT %s < %t.opt namespace Test1 { @@ -380,13 +384,25 @@ D::~D() {} /**** The following has to go at the end of the file ****/ +// checking without opt +// CHECK-NONOPT-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv( +// CHECK-NONOPT-NOT: comdat + // This is from Test5: -// CHECK-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv( -// CHECK-NOT: comdat -// CHECK-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv +// CHECK-NONOPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv + +// This is from Test10: +// CHECK-NONOPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv +// CHECK-NONOPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv + +// Checking with opt +// CHECK-OPT-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(%"struct.Test4B::(anonymous namespace)::C"* %this) unnamed_addr #0 align 2 // This is from Test10: -// CHECK-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv -// CHECK-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv +// CHECK-OPT-LABEL: define linkonce_odr void @_ZN6Test101C3fooEv +// CHECK-OPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv + +// This is from Test5: +// CHECK-OPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv // CHECK: attributes [[NUW]] = { nounwind uwtable{{.*}} } diff --git a/clang/test/CodeGenCXX/virtual-base-ctor.cpp b/clang/test/CodeGenCXX/virtual-base-ctor.cpp index 8c28965c5c2..20a88cd3710 100644 --- a/clang/test/CodeGenCXX/virtual-base-ctor.cpp +++ b/clang/test/CodeGenCXX/virtual-base-ctor.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - -O2 | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -triple %itanium_abi_triple -o - -O2 | opt - -S -globalopt -o - | FileCheck %s struct B; extern B x; diff --git a/clang/test/CodeGenCXX/vtable-assume-load.cpp b/clang/test/CodeGenCXX/vtable-assume-load.cpp new file mode 100644 index 00000000000..80789baa30d --- /dev/null +++ b/clang/test/CodeGenCXX/vtable-assume-load.cpp @@ -0,0 +1,173 @@ +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o %t.ll -O1 -disable-llvm-optzns -fms-extensions +// RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1 -disable-llvm-optzns -fms-extensions + +// RUN: FileCheck --check-prefix=CHECK1 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK2 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK3 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK4 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK-MS --input-file=%t.ms.ll %s + +namespace test1 { + +struct A { + A(); + virtual void foo(); +}; + +struct B : A { + virtual void foo(); +}; + +void g(A *a) { a->foo(); } + +// CHECK1-LABEL: define void @_ZN5test14fooAEv() +// CHECK1: call void @_ZN5test11AC1Ev(%"struct.test1::A"* %a) +// CHECK1: %vtable = load i8**, i8*** %1 +// CHECK1: %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11AE, i64 0, i64 2) +// CHECK1: call void @llvm.assume(i1 %cmp.vtables) +// CHECK1-LABEL: } + +void fooA() { + A a; + g(&a); +} + +// CHECK1-LABEL: define void @_ZN5test14fooBEv() +// CHECK1: call void @_ZN5test11BC1Ev(%"struct.test1::B"* %b) +// CHECK1: %vtable = load i8**, i8*** %1 +// CHECK1: %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11BE, i64 0, i64 2) +// CHECK1: call void @llvm.assume(i1 %cmp.vtables) +// CHECK1-LABEL: } + +void fooB() { + B b; + g(&b); +} +// there should not be any assumes in the ctor that calls base ctor +// CHECK1-LABEL: define linkonce_odr void @_ZN5test11BC2Ev(%"struct.test1::B"* %this) +// CHECK1-NOT: @llvm.assume( +// CHECK1-LABEL: } +} +namespace test2 { +struct A { + A(); + virtual void foo(); +}; + +struct B { + B(); + virtual void bar(); +}; + +struct C : A, B { + C(); + virtual void foo(); +}; +void g(A *a) { a->foo(); } +void h(B *b) { b->bar(); } + +// CHECK2-LABEL: define void @_ZN5test24testEv() +// CHECK2: call void @_ZN5test21CC1Ev(%"struct.test2::C"* %c) +// CHECK2: vtable = load i8**, i8*** %1 +// CHECK2: %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i64 0, i64 2) +// CHECK2: call void @llvm.assume(i1 %cmp.vtables) + +// CHECK2: %2 = bitcast %"struct.test2::C"* %c to i8* +// CHECK2: %add.ptr = getelementptr inbounds i8, i8* %2, i64 8 +// CHECK2: %3 = bitcast i8* %add.ptr to i8*** +// CHECK2: %vtable1 = load i8**, i8*** %3 +// CHECK2: %cmp.vtables2 = icmp eq i8** %vtable1, getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i64 0, i64 5) +// CHECK2: call void @llvm.assume(i1 %cmp.vtables2) + +// CHECK2: call void @_ZN5test21gEPNS_1AE( +// CHECK2-LABEL: } + +void test() { + C c; + g(&c); + h(&c); +} +} + +namespace test3 { +struct A { + A(); +}; + +struct B : A { + B(); + virtual void foo(); +}; + +struct C : virtual A, B { + C(); + virtual void foo(); +}; +void g(B *a) { a->foo(); } + +// CHECK3-LABEL: define void @_ZN5test34testEv() +// CHECK3: call void @_ZN5test31CC1Ev(%"struct.test3::C"* %c) +// CHECK3: %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTVN5test31CE, i64 0, i64 3) +// CHECK3: call void @llvm.assume(i1 %cmp.vtables) +// CHECK3-LABLEL: } +void test() { + C c; + g(&c); +} +} // test3 + +namespace test4 { +struct A { + A(); + virtual void foo(); +}; + +struct B : virtual A { + B(); + virtual void foo(); +}; +struct C : B { + C(); + virtual void foo(); +}; + +void g(C *c) { c->foo(); } + +// CHECK4-LABEL: define void @_ZN5test44testEv() +// CHECK4: call void @_ZN5test41CC1Ev(%"struct.test4::C"* %c) +// CHECK4: %vtable = load i8**, i8*** %1 +// CHECK4: %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i64 0, i64 4) +// CHECK4: call void @llvm.assume(i1 %cmp.vtables) + +// CHECK4: %2 = bitcast %"struct.test4::C"* %c to i8*** +// CHECK4: %vtable1 = load i8**, i8*** %2 +// CHECK4: %cmp.vtables2 = icmp eq i8** %vtable1, getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i64 0, i64 4) +// CHECK4: call void @llvm.assume(i1 %cmp.vtables2) +// CHECK4-LABEL: } + +void test() { + C c; + g(&c); +} +} // test4 + +namespace test5 { + +struct __declspec(novtable) S { + virtual void foo(); +}; + +void g(S &s) { s.foo(); } + +// if struct has novtable specifier, then we can't generate assumes +// CHECK-MS-LABEL: define void @"\01?test@test5@@YAXXZ"() +// CHECK-MS: call x86_thiscallcc %"struct.test5::S"* @"\01??0S@test5@@QAE@XZ"( +// CHECK-MS-NOT: @llvm.assume +// CHECK-MS-LABEL: } + +void test() { + S s; + g(s); +} + +} // test5 diff --git a/clang/test/CodeGenCXX/vtable-available-externally.cpp b/clang/test/CodeGenCXX/vtable-available-externally.cpp index ab090936cbd..860a3fa118e 100644 --- a/clang/test/CodeGenCXX/vtable-available-externally.cpp +++ b/clang/test/CodeGenCXX/vtable-available-externally.cpp @@ -182,8 +182,8 @@ void f() { namespace Test9 { // all virtual functions are outline, so we can assume that it will // be generated in translation unit where foo is defined -// CHECK-TEST9: @_ZTVN5Test91AE = available_externally unnamed_addr constant -// CHECK-TEST9: @_ZTVN5Test91BE = available_externally unnamed_addr constant +// CHECK-TEST9-DAG: @_ZTVN5Test91AE = available_externally unnamed_addr constant +// CHECK-TEST9-DAG: @_ZTVN5Test91BE = available_externally unnamed_addr constant struct A { virtual void foo(); virtual void bar(); @@ -206,7 +206,7 @@ void g() { namespace Test10 { // because A's key function is defined here, vtable is generated in this TU -// CHECK-TEST10: @_ZTVN6Test101AE = unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant struct A { virtual void foo(); virtual void bar(); @@ -214,14 +214,14 @@ struct A { void A::foo() {} // Because key function is inline we will generate vtable as linkonce_odr -// CHECK-TEST10: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant struct D : A { void bar(); }; inline void D::bar() {} // because B has outline key function then we can refer to -// CHECK-TEST10: @_ZTVN6Test101BE = available_externally unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101BE = available_externally unnamed_addr constant struct B : A { void foo(); void bar(); @@ -230,7 +230,7 @@ struct B : A { // C's key function (car) is outline, but C has inline virtual function so we // can't guarantee that we will be able to refer to bar from name // so (at the moment) we can't emit vtable available_externally -// CHECK-TEST10: @_ZTVN6Test101CE = external unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant struct C : A { void bar() {} // defined in body - not key function virtual inline void gar(); // inline in body - not key function @@ -238,7 +238,7 @@ struct C : A { }; // no key function, vtable will be generated everywhere it will be used -// CHECK-TEST10: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant struct E : A {}; void g(A& a) { |

