diff options
| author | Piotr Padlewski <prazek@google.com> | 2015-08-27 21:35:41 +0000 |
|---|---|---|
| committer | Piotr Padlewski <prazek@google.com> | 2015-08-27 21:35:41 +0000 |
| commit | 81461a4350a105f73b40c3212baafd2b66d3ce22 (patch) | |
| tree | 99c95d7c72c6d247efa6911e625241f0b4af0712 /clang/test/CodeGenCXX/vtable-assume-load.cpp | |
| parent | 525f746710c9b132b20b653d5d8bd130e9bd5e59 (diff) | |
| download | bcm5719-llvm-81461a4350a105f73b40c3212baafd2b66d3ce22.tar.gz bcm5719-llvm-81461a4350a105f73b40c3212baafd2b66d3ce22.zip | |
Assume loads fix #2
There was linker problem, and it turns out that it is not always safe
to refer to vtable. If the vtable is used, then we can refer to it
without any problem, but because we don't know when it will be used or
not, we can only check if vtable is external or it is safe to to emit it
speculativly (when class it doesn't have any inline virtual functions).
It should be fixed in the future.
http://reviews.llvm.org/D12385
llvm-svn: 246214
Diffstat (limited to 'clang/test/CodeGenCXX/vtable-assume-load.cpp')
| -rw-r--r-- | clang/test/CodeGenCXX/vtable-assume-load.cpp | 133 |
1 files changed, 128 insertions, 5 deletions
diff --git a/clang/test/CodeGenCXX/vtable-assume-load.cpp b/clang/test/CodeGenCXX/vtable-assume-load.cpp index 5ea9e755242..17cd477f19f 100644 --- a/clang/test/CodeGenCXX/vtable-assume-load.cpp +++ b/clang/test/CodeGenCXX/vtable-assume-load.cpp @@ -6,7 +6,9 @@ // 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 - +// RUN: FileCheck --check-prefix=CHECK6 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK7 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK8 --input-file=%t.ll %s namespace test1 { struct A { @@ -150,7 +152,7 @@ void test() { } } // test4 -namespace test5 { +namespace testMS { struct __declspec(novtable) S { virtual void foo(); @@ -159,8 +161,8 @@ struct __declspec(novtable) S { 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-LABEL: define void @"\01?test@testMS@@YAXXZ"() +// CHECK-MS: call x86_thiscallcc %"struct.testMS::S"* @"\01??0S@testMS@@QAE@XZ"( // CHECK-MS-NOT: @llvm.assume // CHECK-MS-LABEL: } @@ -169,4 +171,125 @@ void test() { g(s); } -} // test5 +} // testMS + +namespace test6 { +// CHECK6: @_ZTVN5test61AE = external +struct A { + A(); + virtual void foo(); + virtual ~A() {} +}; +struct B : A { + B(); +}; +// Because A's vtable is external, it's safe to generate assumption loads. +// CHECK6-LABEL: define void @_ZN5test61gEv() +// CHECK6: call void @_ZN5test61AC1Ev( +// CHECK6: call void @llvm.assume( + +// We can't emit assumption loads for B, because if we would refer to vtable +// it would refer to functions that will not be able to find (like implicit +// inline destructor). + +// CHECK6-LABEL: call void @_ZN5test61BC1Ev( +// CHECK6-NOT: call void @llvm.assume( +// CHECK6-LABEL: } +void g() { + A *a = new A; + B *b = new B; +} + +} + +namespace test7 { +// Because A's key function is defined here, vtable is generated in this TU +// CHECK7: @_ZTVN5test71AE = unnamed_addr constant +struct A { + A(); + virtual void foo(); + virtual void bar(); +}; +void A::foo() {} + +// CHECK7-LABEL: define void @_ZN5test71gEv() +// CHECK7: call void @_ZN5test71AC1Ev( +// CHECK7: call void @llvm.assume( +// CHECK7-LABEL: } +void g() { + A *a = new A(); + a->bar(); +} +} + +namespace test8 { + +struct A { + virtual void foo(); + virtual void bar(); +}; + +// CHECK8-DAG: @_ZTVN5test81BE = available_externally unnamed_addr constant +struct B : A { + B(); + void foo(); + void bar(); +}; + +// CHECK8-DAG: @_ZTVN5test81CE = linkonce_odr unnamed_addr constant +struct C : A { + C(); + void bar(); + void foo() {} +}; +inline void C::bar() {} + +// CHECK8-DAG: @_ZTVN5test81DE = external unnamed_addr constant +struct D : A { + D(); + void foo(); + void inline bar(); +}; +void D::bar() {} + +// CHECK8-DAG: @_ZTVN5test81EE = linkonce_odr unnamed_addr constant +struct E : A { + E(); +}; + +// CHECK8-LABEL: define void @_ZN5test81bEv() +// CHECK8: call void @llvm.assume( +// CHECK8-LABEL: } +void b() { + B b; + b.bar(); +} + +// FIXME: C has inline virtual functions which prohibits as from generating +// assumption loads, but because vtable is generated in this TU (key function +// defined here) it would be correct to refer to it. +// CHECK8-LABEL: define void @_ZN5test81cEv() +// CHECK8-NOT: call void @llvm.assume( +// CHECK8-LABEL: } +void c() { + C c; + c.bar(); +} + +// CHECK8-LABEL: define void @_ZN5test81dEv() +// CHECK8: call void @llvm.assume( +// CHECK8-LABEL: } +void d() { + D d; + d.bar(); +} + +// CHECK8-LABEL: define void @_ZN5test81eEv() +// CHECK8: call void @llvm.assume( +// CHECK8-LABEL: } +void e() { + E e; + e.bar(); +} +} + |

