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 // FIXME: Assume load should not require -fstrict-vtable-pointers 3 4 // RUN: FileCheck --check-prefix=CHECK1 --input-file=%t.ll %s 5 // RUN: FileCheck --check-prefix=CHECK2 --input-file=%t.ll %s 6 // RUN: FileCheck --check-prefix=CHECK3 --input-file=%t.ll %s 7 // RUN: FileCheck --check-prefix=CHECK4 --input-file=%t.ll %s 8 // RUN: FileCheck --check-prefix=CHECK5 --input-file=%t.ll %s 9 // RUN: FileCheck --check-prefix=CHECK6 --input-file=%t.ll %s 10 // RUN: FileCheck --check-prefix=CHECK7 --input-file=%t.ll %s 11 // RUN: FileCheck --check-prefix=CHECK8 --input-file=%t.ll %s 12 namespace test1 { 13 14 struct A { 15 A(); 16 virtual void foo(); 17 }; 18 19 struct B : A { 20 virtual void foo(); 21 }; 22 23 void g(A *a) { a->foo(); } 24 25 // CHECK1-LABEL: define{{.*}} void @_ZN5test14fooAEv() 26 // CHECK1: call void @_ZN5test11AC1Ev(ptr 27 // CHECK1: %[[VTABLE:.*]] = load ptr addrspace(1), ptr %{{.*}} 28 // 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) 29 // CHECK1: call void @llvm.assume(i1 %[[CMP]]) 30 // CHECK1-LABEL: {{^}}} 31 32 void fooA() { 33 A a; 34 g(&a); 35 } 36 37 // CHECK1-LABEL: define{{.*}} void @_ZN5test14fooBEv() 38 // CHECK1: call void @_ZN5test11BC1Ev(ptr {{[^,]*}} %{{.*}}) 39 // CHECK1: %[[VTABLE:.*]] = load ptr addrspace(1), ptr %{{.*}} 40 // 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) 41 // CHECK1: call void @llvm.assume(i1 %[[CMP]]) 42 // CHECK1-LABEL: {{^}}} 43 44 void fooB() { 45 B b; 46 g(&b); 47 } 48 // there should not be any assumes in the ctor that calls base ctor 49 // CHECK1-LABEL: define linkonce_odr void @_ZN5test11BC2Ev(ptr 50 // CHECK1-NOT: @llvm.assume( 51 // CHECK1-LABEL: {{^}}} 52 } 53 namespace test2 { 54 struct A { 55 A(); 56 virtual void foo(); 57 }; 58 59 struct B { 60 B(); 61 virtual void bar(); 62 }; 63 64 struct C : A, B { 65 C(); 66 virtual void foo(); 67 }; 68 void g(A *a) { a->foo(); } 69 void h(B *b) { b->bar(); } 70 71 // CHECK2-LABEL: define{{.*}} void @_ZN5test24testEv() 72 // CHECK2: call void @_ZN5test21CC1Ev(ptr 73 // CHECK2: %[[VTABLE:.*]] = load ptr addrspace(1), ptr {{.*}} 74 // 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) 75 // CHECK2: call void @llvm.assume(i1 %[[CMP]]) 76 77 // CHECK2: %[[ADD_PTR:.*]] = getelementptr inbounds i8, ptr %{{.*}}, i64 8 78 // CHECK2: %[[VTABLE2:.*]] = load ptr addrspace(1), ptr %[[ADD_PTR]] 79 // 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) 80 // CHECK2: call void @llvm.assume(i1 %[[CMP2]]) 81 82 // CHECK2: call void @_ZN5test21gEPNS_1AE( 83 // CHECK2-LABEL: {{^}}} 84 85 void test() { 86 C c; 87 g(&c); 88 h(&c); 89 } 90 } 91 92 namespace test3 { 93 struct A { 94 A(); 95 }; 96 97 struct B : A { 98 B(); 99 virtual void foo(); 100 }; 101 102 struct C : virtual A, B { 103 C(); 104 virtual void foo(); 105 }; 106 void g(B *a) { a->foo(); } 107 108 // CHECK3-LABEL: define{{.*}} void @_ZN5test34testEv() 109 // CHECK3: call void @_ZN5test31CC1Ev(ptr 110 // 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) 111 // CHECK3: call void @llvm.assume(i1 %[[CMP]]) 112 // CHECK3-LABLEL: } 113 void test() { 114 C c; 115 g(&c); 116 } 117 } // test3 118 119 namespace test4 { 120 struct A { 121 A(); 122 virtual void foo(); 123 }; 124 125 struct B : virtual A { 126 B(); 127 virtual void foo(); 128 }; 129 struct C : B { 130 C(); 131 virtual void foo(); 132 }; 133 134 void g(C *c) { c->foo(); } 135 136 // CHECK4-LABEL: define{{.*}} void @_ZN5test44testEv() 137 // CHECK4: call void @_ZN5test41CC1Ev(ptr 138 // CHECK4: %[[VTABLE:.*]] = load ptr addrspace(1), ptr %{{.*}} 139 // 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) 140 // CHECK4: call void @llvm.assume(i1 %[[CMP]] 141 142 // CHECK4: %[[VTABLE2:.*]] = load ptr addrspace(1), ptr %{{.*}} 143 // 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) 144 // CHECK4: call void @llvm.assume(i1 %[[CMP2]]) 145 // CHECK4-LABEL: {{^}}} 146 147 void test() { 148 C c; 149 g(&c); 150 } 151 } // test4 152 153 namespace test6 { 154 struct A { 155 A(); 156 virtual void foo(); 157 virtual ~A() {} 158 }; 159 struct B : A { 160 B(); 161 }; 162 // FIXME: Because A's vtable is external, and no virtual functions are hidden, 163 // it's safe to generate assumption loads. 164 // CHECK5-LABEL: define{{.*}} void @_ZN5test61gEv() 165 // CHECK5: call void @_ZN5test61AC1Ev( 166 // CHECK5-NOT: call void @llvm.assume( 167 168 // We can't emit assumption loads for B, because if we would refer to vtable 169 // it would refer to functions that will not be able to find (like implicit 170 // inline destructor). 171 172 // CHECK5-LABEL: call void @_ZN5test61BC1Ev( 173 // CHECK5-NOT: call void @llvm.assume( 174 // CHECK5-LABEL: {{^}}} 175 void g() { 176 A *a = new A; 177 B *b = new B; 178 } 179 } 180 181 namespace test7 { 182 // Because A's key function is defined here, vtable is generated in this TU 183 // CHECK6: @_ZTVN5test71AE ={{.*}} unnamed_addr addrspace(1) constant 184 struct A { 185 A(); 186 virtual void foo(); 187 virtual void bar(); 188 }; 189 void A::foo() {} 190 191 // CHECK6-LABEL: define{{.*}} void @_ZN5test71gEv() 192 // CHECK6: call void @_ZN5test71AC1Ev( 193 // CHECK6: call void @llvm.assume( 194 // CHECK6-LABEL: {{^}}} 195 void g() { 196 A *a = new A(); 197 a->bar(); 198 } 199 } 200 201 namespace test8 { 202 203 struct A { 204 virtual void foo(); 205 virtual void bar(); 206 }; 207 208 // CHECK7-DAG: @_ZTVN5test81BE = available_externally unnamed_addr addrspace(1) constant 209 struct B : A { 210 B(); 211 void foo(); 212 void bar(); 213 }; 214 215 // CHECK7-DAG: @_ZTVN5test81CE = linkonce_odr unnamed_addr addrspace(1) constant 216 struct C : A { 217 C(); 218 void bar(); 219 void foo() {} 220 }; 221 inline void C::bar() {} 222 223 struct D : A { 224 D(); 225 void foo(); 226 void inline bar(); 227 }; 228 void D::bar() {} 229 230 // CHECK7-DAG: @_ZTVN5test81EE = linkonce_odr unnamed_addr addrspace(1) constant 231 struct E : A { 232 E(); 233 }; 234 235 // CHECK7-LABEL: define{{.*}} void @_ZN5test81bEv() 236 // CHECK7: call void @llvm.assume( 237 // CHECK7-LABEL: {{^}}} 238 void b() { 239 B b; 240 b.bar(); 241 } 242 243 // FIXME: C has inline virtual functions which prohibits as from generating 244 // assumption loads, but because vtable is generated in this TU (key function 245 // defined here) it would be correct to refer to it. 246 // CHECK7-LABEL: define{{.*}} void @_ZN5test81cEv() 247 // CHECK7-NOT: call void @llvm.assume( 248 // CHECK7-LABEL: {{^}}} 249 void c() { 250 C c; 251 c.bar(); 252 } 253 254 // FIXME: We could generate assumption loads here. 255 // CHECK7-LABEL: define{{.*}} void @_ZN5test81dEv() 256 // CHECK7-NOT: call void @llvm.assume( 257 // CHECK7-LABEL: {{^}}} 258 void d() { 259 D d; 260 d.bar(); 261 } 262 263 // CHECK7-LABEL: define{{.*}} void @_ZN5test81eEv() 264 // CHECK7: call void @llvm.assume( 265 // CHECK7-LABEL: {{^}}} 266 void e() { 267 E e; 268 e.bar(); 269 } 270 } 271 272 namespace test9 { 273 274 struct S { 275 S(); 276 __attribute__((visibility("hidden"))) virtual void doStuff(); 277 }; 278 279 // CHECK8-LABEL: define{{.*}} void @_ZN5test94testEv() 280 // CHECK8-NOT: @llvm.assume( 281 // CHECK8: } 282 void test() { 283 S *s = new S(); 284 s->doStuff(); 285 delete s; 286 } 287 } 288 289