1 ; RUN: opt < %s -globaldce -S | FileCheck %s
3 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
5 declare dso_local noalias nonnull i8* @_Znwm(i64)
6 declare { i8*, i1 } @llvm.type.checked.load(i8*, i32, metadata)
8 ; %struct.A is a C++ struct with two virtual functions, A::foo and A::bar. The
9 ; !vcall_visibility metadata is set on the vtable, so we know that all virtual
10 ; calls through this vtable are visible and use the @llvm.type.checked.load
11 ; intrinsic. Function test_A makes a call to A::foo, but there is no call to
12 ; A::bar anywhere, so A::bar can be deleted, and its vtable slot replaced with
15 %struct.A = type { i32 (...)** }
17 ; The pointer to A::bar in the vtable can be removed, because it will never be
18 ; loaded. We replace it with null to keep the layout the same. Because it is at
19 ; the end of the vtable we could potentially shrink the vtable, but don't
21 ; CHECK: @_ZTV1A = internal unnamed_addr constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* null, i8* bitcast (i32 (%struct.A*)* @_ZN1A3fooEv to i8*), i8* null] }
22 @_ZTV1A = internal unnamed_addr constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* null, i8* bitcast (i32 (%struct.A*)* @_ZN1A3fooEv to i8*), i8* bitcast (i32 (%struct.A*)* @_ZN1A3barEv to i8*)] }, align 8, !type !0, !type !1, !type !2, !vcall_visibility !3
24 ; A::foo is called, so must be retained.
25 ; CHECK: define internal i32 @_ZN1A3fooEv(
26 define internal i32 @_ZN1A3fooEv(%struct.A* nocapture readnone %this) {
31 ; A::bar is not used, so can be deleted.
32 ; CHECK-NOT: define internal i32 @_ZN1A3barEv(
33 define internal i32 @_ZN1A3barEv(%struct.A* nocapture readnone %this) {
38 define dso_local i32 @test_A() {
40 %call = tail call i8* @_Znwm(i64 8)
41 %0 = bitcast i8* %call to %struct.A*
42 %1 = bitcast i8* %call to i32 (...)***
43 store i32 (...)** bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTV1A, i64 0, inrange i32 0, i64 2) to i32 (...)**), i32 (...)*** %1, align 8
44 %2 = tail call { i8*, i1 } @llvm.type.checked.load(i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTV1A, i64 0, inrange i32 0, i64 2) to i8*), i32 0, metadata !"_ZTS1A"), !nosanitize !9
45 %3 = extractvalue { i8*, i1 } %2, 0, !nosanitize !9
46 %4 = bitcast i8* %3 to i32 (%struct.A*)*, !nosanitize !9
47 %call1 = tail call i32 %4(%struct.A* nonnull %0)
51 !0 = !{i64 16, !"_ZTS1A"}
52 !1 = !{i64 16, !"_ZTSM1AFivE.virtual"}
53 !2 = !{i64 24, !"_ZTSM1AFivE.virtual"}