[AMDGPU][True16][CodeGen] true16 codegen pattern for v_med3_u/i16 (#121850)
[llvm-project.git] / clang / test / CodeGenCXX / vtable-assume-load-address-space.cpp
blobe8d3a8407cda73fa116b2bd918ae507062be7bc7
1 // RUN: %clang_cc1 %s -triple=amdgcn-amd-amdhsa -std=c++11 -emit-llvm -o %t.ll -O1 -disable-llvm-passes -fms-extensions -fstrict-vtable-pointers
2 // RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1 -disable-llvm-passes -fms-extensions -fstrict-vtable-pointers
3 // RUN: %clang_cc1 %s -triple=spirv64-amd-amdhsa -std=c++11 -emit-llvm -o %t.ll -O1 -disable-llvm-passes -fms-extensions -fstrict-vtable-pointers
4 // FIXME: Assume load should not require -fstrict-vtable-pointers
6 // RUN: FileCheck --check-prefix=CHECK1 --input-file=%t.ll %s
7 // RUN: FileCheck --check-prefix=CHECK2 --input-file=%t.ll %s
8 // RUN: FileCheck --check-prefix=CHECK3 --input-file=%t.ll %s
9 // RUN: FileCheck --check-prefix=CHECK4 --input-file=%t.ll %s
10 // RUN: FileCheck --check-prefix=CHECK-MS --input-file=%t.ms.ll %s
11 // RUN: FileCheck --check-prefix=CHECK6 --input-file=%t.ll %s
12 // RUN: FileCheck --check-prefix=CHECK7 --input-file=%t.ll %s
13 // RUN: FileCheck --check-prefix=CHECK8 --input-file=%t.ll %s
14 // RUN: FileCheck --check-prefix=CHECK9 --input-file=%t.ll %s
15 namespace test1 {
17 struct A {
18 A();
19 virtual void foo();
22 struct B : A {
23 virtual void foo();
26 void g(A *a) { a->foo(); }
28 // CHECK1-LABEL: define{{.*}} void @_ZN5test14fooAEv()
29 // CHECK1: call{{.*}} void @_ZN5test11AC1Ev(ptr {{((addrspace(4)){0,1})}}
30 // CHECK1: %[[VTABLE:.*]] = load ptr addrspace(1), ptr {{((addrspace(4)){0,1})}}{{.*}}%{{.*}}
31 // CHECK1: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test11AE, i32 0, i32 0, i32 2)
32 // CHECK1: call{{.*}} void @llvm.assume(i1 %[[CMP]])
33 // CHECK1-LABEL: {{^}}}
35 void fooA() {
36 A a;
37 g(&a);
40 // CHECK1-LABEL: define{{.*}} void @_ZN5test14fooBEv()
41 // CHECK1: call{{.*}} void @_ZN5test11BC1Ev(ptr {{[^,]*}} %{{.*}})
42 // CHECK1: %[[VTABLE:.*]] = load ptr addrspace(1), ptr {{((addrspace(4)){0,1})}}{{.*}}%{{.*}}
43 // CHECK1: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test11BE, i32 0, i32 0, i32 2)
44 // CHECK1: call{{.*}} void @llvm.assume(i1 %[[CMP]])
45 // CHECK1-LABEL: {{^}}}
47 void fooB() {
48 B b;
49 g(&b);
51 // there should not be any assumes in the ctor that calls base ctor
52 // CHECK1-LABEL: define linkonce_odr{{.*}} void @_ZN5test11BC2Ev(ptr
53 // CHECK1-NOT: @llvm.assume(
54 // CHECK1-LABEL: {{^}}}
56 namespace test2 {
57 struct A {
58 A();
59 virtual void foo();
62 struct B {
63 B();
64 virtual void bar();
67 struct C : A, B {
68 C();
69 virtual void foo();
71 void g(A *a) { a->foo(); }
72 void h(B *b) { b->bar(); }
74 // CHECK2-LABEL: define{{.*}} void @_ZN5test24testEv()
75 // CHECK2: call{{.*}} void @_ZN5test21CC1Ev(ptr
76 // CHECK2: %[[VTABLE:.*]] = load ptr addrspace(1), ptr {{.*}}
77 // CHECK2: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test21CE, i32 0, i32 0, i32 2)
78 // CHECK2: call{{.*}} void @llvm.assume(i1 %[[CMP]])
80 // CHECK2: %[[ADD_PTR:.*]] = getelementptr inbounds i8, ptr {{((addrspace(4)){0,1})}}{{.*}}%{{.*}}, i64 8
81 // CHECK2: %[[VTABLE2:.*]] = load ptr addrspace(1), ptr {{((addrspace(4)){0,1})}}{{.*}}%[[ADD_PTR]]
82 // CHECK2: %[[CMP2:.*]] = icmp eq ptr addrspace(1) %[[VTABLE2]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test21CE, i32 0, i32 1, i32 2)
83 // CHECK2: call{{.*}} void @llvm.assume(i1 %[[CMP2]])
85 // CHECK2: call{{.*}} void @_ZN5test21gEPNS_1AE(
86 // CHECK2-LABEL: {{^}}}
88 void test() {
89 C c;
90 g(&c);
91 h(&c);
95 namespace test3 {
96 struct A {
97 A();
100 struct B : A {
101 B();
102 virtual void foo();
105 struct C : virtual A, B {
106 C();
107 virtual void foo();
109 void g(B *a) { a->foo(); }
111 // CHECK3-LABEL: define{{.*}} void @_ZN5test34testEv()
112 // CHECK3: call{{.*}} void @_ZN5test31CC1Ev(ptr
113 // CHECK3: %[[CMP:.*]] = icmp eq ptr addrspace(1) %{{.*}}, getelementptr inbounds inrange(-24, 8) ({ [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test31CE, i32 0, i32 0, i32 3)
114 // CHECK3: call{{.*}} void @llvm.assume(i1 %[[CMP]])
115 // CHECK3-LABLEL: }
116 void test() {
117 C c;
118 g(&c);
120 } // test3
122 namespace test4 {
123 struct A {
124 A();
125 virtual void foo();
128 struct B : virtual A {
129 B();
130 virtual void foo();
132 struct C : B {
133 C();
134 virtual void foo();
137 void g(C *c) { c->foo(); }
139 // CHECK4-LABEL: define{{.*}} void @_ZN5test44testEv()
140 // CHECK4: call{{.*}} void @_ZN5test41CC1Ev(ptr
141 // CHECK4: %[[VTABLE:.*]] = load ptr addrspace(1), ptr {{((addrspace(4)){0,1})}}{{.*}}%{{.*}}
142 // CHECK4: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds inrange(-32, 8) ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test41CE, i32 0, i32 0, i32 4)
143 // CHECK4: call{{.*}} void @llvm.assume(i1 %[[CMP]]
145 // CHECK4: %[[VTABLE2:.*]] = load ptr addrspace(1), ptr {{((addrspace(4)){0,1})}}{{.*}}%{{.*}}
146 // CHECK4: %[[CMP2:.*]] = icmp eq ptr addrspace(1) %[[VTABLE2]], getelementptr inbounds inrange(-32, 8) ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test41CE, i32 0, i32 0, i32 4)
147 // CHECK4: call{{.*}} void @llvm.assume(i1 %[[CMP2]])
148 // CHECK4-LABEL: {{^}}}
150 void test() {
151 C c;
152 g(&c);
154 } // test4
156 namespace testMS {
158 struct __declspec(novtable) S {
159 virtual void foo();
162 void g(S &s) { s.foo(); }
164 // if struct has novtable specifier, then we can't generate assumes
165 // CHECK-MS-LABEL: define dso_local void @"?test@testMS@@YAXXZ"()
166 // CHECK-MS: call x86_thiscallcc noundef ptr @"??0S@testMS@@QAE@XZ"(
167 // CHECK-MS-NOT: @llvm.assume
168 // CHECK-MS-LABEL: {{^}}}
170 void test() {
171 S s;
172 g(s);
175 } // testMS
177 namespace test6 {
178 struct A {
179 A();
180 virtual void foo();
181 virtual ~A() {}
183 struct B : A {
184 B();
186 // FIXME: Because A's vtable is external, and no virtual functions are hidden,
187 // it's safe to generate assumption loads.
188 // CHECK6-LABEL: define{{.*}} void @_ZN5test61gEv()
189 // CHECK6: call{{.*}} void @_ZN5test61AC1Ev(
190 // CHECK6-NOT: call void @llvm.assume(
192 // We can't emit assumption loads for B, because if we would refer to vtable
193 // it would refer to functions that will not be able to find (like implicit
194 // inline destructor).
196 // CHECK6-LABEL: call{{.*}} void @_ZN5test61BC1Ev(
197 // CHECK6-NOT: call void @llvm.assume(
198 // CHECK6-LABEL: {{^}}}
199 void g() {
200 A *a = new A;
201 B *b = new B;
205 namespace test7 {
206 // Because A's key function is defined here, vtable is generated in this TU
207 // CHECK7: @_ZTVN5test71AE ={{.*}} unnamed_addr addrspace(1) constant
208 struct A {
209 A();
210 virtual void foo();
211 virtual void bar();
213 void A::foo() {}
215 // CHECK7-LABEL: define{{.*}} void @_ZN5test71gEv()
216 // CHECK7: call{{.*}} void @_ZN5test71AC1Ev(
217 // CHECK7: call{{.*}} void @llvm.assume(
218 // CHECK7-LABEL: {{^}}}
219 void g() {
220 A *a = new A();
221 a->bar();
225 namespace test8 {
227 struct A {
228 virtual void foo();
229 virtual void bar();
232 // CHECK8-DAG: @_ZTVN5test81BE = available_externally unnamed_addr addrspace(1) constant
233 struct B : A {
234 B();
235 void foo();
236 void bar();
239 // CHECK8-DAG: @_ZTVN5test81CE = linkonce_odr unnamed_addr addrspace(1) constant
240 struct C : A {
241 C();
242 void bar();
243 void foo() {}
245 inline void C::bar() {}
247 struct D : A {
248 D();
249 void foo();
250 void inline bar();
252 void D::bar() {}
254 // CHECK8-DAG: @_ZTVN5test81EE = linkonce_odr unnamed_addr addrspace(1) constant
255 struct E : A {
256 E();
259 // CHECK8-LABEL: define{{.*}} void @_ZN5test81bEv()
260 // CHECK8: call{{.*}} void @llvm.assume(
261 // CHECK8-LABEL: {{^}}}
262 void b() {
263 B b;
264 b.bar();
267 // FIXME: C has inline virtual functions which prohibits as from generating
268 // assumption loads, but because vtable is generated in this TU (key function
269 // defined here) it would be correct to refer to it.
270 // CHECK8-LABEL: define{{.*}} void @_ZN5test81cEv()
271 // CHECK8-NOT: call void @llvm.assume(
272 // CHECK8-LABEL: {{^}}}
273 void c() {
274 C c;
275 c.bar();
278 // FIXME: We could generate assumption loads here.
279 // CHECK8-LABEL: define{{.*}} void @_ZN5test81dEv()
280 // CHECK8-NOT: call void @llvm.assume(
281 // CHECK8-LABEL: {{^}}}
282 void d() {
283 D d;
284 d.bar();
287 // CHECK8-LABEL: define{{.*}} void @_ZN5test81eEv()
288 // CHECK8: call{{.*}} void @llvm.assume(
289 // CHECK8-LABEL: {{^}}}
290 void e() {
291 E e;
292 e.bar();
296 namespace test9 {
298 struct S {
299 S();
300 __attribute__((visibility("hidden"))) virtual void doStuff();
303 // CHECK9-LABEL: define{{.*}} void @_ZN5test94testEv()
304 // CHECK9-NOT: @llvm.assume(
305 // CHECK9: }
306 void test() {
307 S *s = new S();
308 s->doStuff();
309 delete s;