27
27
; NOENABLESPLITFLAG-DAG: [[B:\^[0-9]+]] = gv: (name: "_ZTV1B", {{.*}} vTableFuncs: ((virtFunc: [[Bf]], offset: 16), (virtFunc: [[An]], offset: 24)), refs: ([[Bf]], [[An]])
28
28
; NOENABLESPLITFLAG-DAG: [[C:\^[0-9]+]] = gv: (name: "_ZTV1C", {{.*}} vTableFuncs: ((virtFunc: [[Cf]], offset: 16), (virtFunc: [[An]], offset: 24)), refs: ([[An]], [[Cf]])
29
29
; NOENABLESPLITFLAG-DAG: [[D:\^[0-9]+]] = gv: (name: "_ZTV1D", {{.*}} vTableFuncs: ((virtFunc: [[Dm]], offset: 16)), refs: ([[Dm]])
30
+ ; NOENABLESPLITFLAG-DAG: [[B_RV:\^[0-9]+]] = gv: (name: "_ZTV1B_RV", {{.*}} vTableFuncs: ((virtFunc: [[Bf]], offset: 8), (virtFunc: [[An]], offset: 12)), refs: ([[B_RV]], [[Bf]], [[An]])
31
+ ; NOENABLESPLITFLAG-DAG: [[C_RV:\^[0-9]+]] = gv: (name: "_ZTV1C_RV", {{.*}} vTableFuncs: ((virtFunc: [[Cf]], offset: 8), (virtFunc: [[An]], offset: 12)), refs: ([[C_RV]], [[An]], [[Cf]])
32
+ ; NOENABLESPLITFLAG-DAG: [[D_RV:\^[0-9]+]] = gv: (name: "_ZTV1D_RV", {{.*}} vTableFuncs: ((virtFunc: [[Dm]], offset: 8)), refs: ([[D_RV]], [[Dm]])
30
33
; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name: "_ZTS1A", summary: ((offset: 16, [[B]]), (offset: 16, [[C]])))
31
34
; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name: "_ZTS1B", summary: ((offset: 16, [[B]])))
32
35
; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name: "_ZTS1C", summary: ((offset: 16, [[C]])))
36
+ ; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name: "_ZTS1A_RV", summary: ((offset: 8, [[B_RV]]), (offset: 8, [[C_RV]])))
37
+ ; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name: "_ZTS1B_RV", summary: ((offset: 8, [[B_RV]])))
38
+ ; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name: "_ZTS1C_RV", summary: ((offset: 8, [[C_RV]])))
33
39
; Type Id on _ZTV1D should have been promoted
34
40
; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name: "1.{{.*}}", summary: ((offset: 16, [[D]])))
41
+ ; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name: "2.{{.*}}", summary: ((offset: 8, [[D_RV]])))
35
42
36
43
; Index based WPD
37
44
; RUN: llvm-lto2 run %t2.o -save-temps -pass-remarks=. \
38
45
; RUN: -whole-program-visibility \
39
46
; RUN: -o %t3 \
40
47
; RUN: -r=%t2.o,test,px \
48
+ ; RUN: -r=%t2.o,test_rv,px \
41
49
; RUN: -r=%t2.o,_ZN1A1nEi,p \
42
50
; RUN: -r=%t2.o,_ZN1B1fEi,p \
43
51
; RUN: -r=%t2.o,_ZN1C1fEi,p \
44
52
; RUN: -r=%t2.o,_ZN1D1mEi,p \
45
53
; RUN: -r=%t2.o,_ZTV1B,px \
46
54
; RUN: -r=%t2.o,_ZTV1C,px \
47
- ; RUN: -r=%t2.o,_ZTV1D,px 2>&1 | FileCheck %s --check-prefix=REMARK
55
+ ; RUN: -r=%t2.o,_ZTV1D,px \
56
+ ; RUN: -r=%t2.o,_ZTV1B_RV,px \
57
+ ; RUN: -r=%t2.o,_ZTV1C_RV,px \
58
+ ; RUN: -r=%t2.o,_ZTV1D_RV,px \
59
+ ; RUN: 2>&1 | FileCheck %s --check-prefix=REMARK
48
60
; RUN: llvm-dis %t3.1.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-IR
49
61
50
62
; Check that we're able to prevent specific function from being
54
66
; RUN: -wholeprogramdevirt-skip=_ZN1A1nEi \
55
67
; RUN: -o %t3 \
56
68
; RUN: -r=%t2.o,test,px \
69
+ ; RUN: -r=%t2.o,test_rv,px \
57
70
; RUN: -r=%t2.o,_ZN1A1nEi,p \
58
71
; RUN: -r=%t2.o,_ZN1B1fEi,p \
59
72
; RUN: -r=%t2.o,_ZN1C1fEi,p \
60
73
; RUN: -r=%t2.o,_ZN1D1mEi,p \
61
74
; RUN: -r=%t2.o,_ZTV1B,px \
62
75
; RUN: -r=%t2.o,_ZTV1C,px \
63
- ; RUN: -r=%t2.o,_ZTV1D,px 2>&1 | FileCheck %s --check-prefix=SKIP
76
+ ; RUN: -r=%t2.o,_ZTV1D,px \
77
+ ; RUN: -r=%t2.o,_ZTV1B_RV,px \
78
+ ; RUN: -r=%t2.o,_ZTV1C_RV,px \
79
+ ; RUN: -r=%t2.o,_ZTV1D_RV,px \
80
+ ; RUN: 2>&1 | FileCheck %s --check-prefix=SKIP
64
81
65
82
; RUN: llvm-lto2 run %t.o -save-temps -pass-remarks=. \
66
83
; RUN: -whole-program-visibility \
67
84
; RUN: -o %t3 \
68
85
; RUN: -r=%t.o,test,px \
86
+ ; RUN: -r=%t.o,test_rv,px \
69
87
; RUN: -r=%t.o,_ZN1A1nEi,p \
70
88
; RUN: -r=%t.o,_ZN1B1fEi,p \
71
89
; RUN: -r=%t.o,_ZN1C1fEi,p \
72
90
; RUN: -r=%t.o,_ZN1D1mEi,p \
73
91
; RUN: -r=%t.o,_ZTV1B, \
74
92
; RUN: -r=%t.o,_ZTV1C, \
75
93
; RUN: -r=%t.o,_ZTV1D, \
94
+ ; RUN: -r=%t.o,_ZTV1B_RV, \
95
+ ; RUN: -r=%t.o,_ZTV1C_RV, \
96
+ ; RUN: -r=%t.o,_ZTV1D_RV, \
76
97
; RUN: -r=%t.o,_ZN1A1nEi, \
77
98
; RUN: -r=%t.o,_ZN1B1fEi, \
78
99
; RUN: -r=%t.o,_ZN1C1fEi, \
79
100
; RUN: -r=%t.o,_ZN1D1mEi, \
80
101
; RUN: -r=%t.o,_ZTV1B,px \
81
102
; RUN: -r=%t.o,_ZTV1C,px \
82
- ; RUN: -r=%t.o,_ZTV1D,px 2>&1 | FileCheck %s --check-prefix=REMARK --dump-input=fail
103
+ ; RUN: -r=%t.o,_ZTV1D,px \
104
+ ; RUN: -r=%t.o,_ZTV1B_RV,px \
105
+ ; RUN: -r=%t.o,_ZTV1C_RV,px \
106
+ ; RUN: -r=%t.o,_ZTV1D_RV,px \
107
+ ; RUN: 2>&1 | FileCheck %s --check-prefix=REMARK --dump-input=fail
83
108
; RUN: llvm-dis %t3.1.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-IR
84
109
110
+ ; REMARK-DAG: single-impl: devirtualized a call to _ZN1A1nEi
111
+ ; REMARK-DAG: single-impl: devirtualized a call to _ZN1D1mEi
85
112
; REMARK-DAG: single-impl: devirtualized a call to _ZN1A1nEi
86
113
; REMARK-DAG: single-impl: devirtualized a call to _ZN1D1mEi
87
114
@@ -99,6 +126,25 @@ target triple = "x86_64-grtev4-linux-gnu"
99
126
@_ZTV1C = constant { [4 x ptr ] } { [4 x ptr ] [ptr null , ptr undef , ptr @_ZN1C1fEi , ptr @_ZN1A1nEi ] }, !type !0 , !type !2
100
127
@_ZTV1D = constant { [3 x ptr ] } { [3 x ptr ] [ptr null , ptr undef , ptr @_ZN1D1mEi ] }, !type !3
101
128
129
+ @_ZTV1B_RV = constant { [4 x i32 ] } { [4 x i32 ] [
130
+ i32 0 ,
131
+ i32 undef ,
132
+ i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1B1fEi to i64 ), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32 ] }, ptr @_ZTV1B_RV , i32 0 , i32 0 , i32 2 ) to i64 )) to i32 ),
133
+ i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A1nEi to i64 ), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32 ] }, ptr @_ZTV1B_RV , i32 0 , i32 0 , i32 3 ) to i64 )) to i32 )
134
+ ] }, !type !7 , !type !8
135
+
136
+ @_ZTV1C_RV = constant { [4 x i32 ] } { [4 x i32 ] [
137
+ i32 0 ,
138
+ i32 undef ,
139
+ i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1C1fEi to i64 ), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32 ] }, ptr @_ZTV1C_RV , i32 0 , i32 0 , i32 2 ) to i64 )) to i32 ),
140
+ i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A1nEi to i64 ), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32 ] }, ptr @_ZTV1C_RV , i32 0 , i32 0 , i32 3 ) to i64 )) to i32 )
141
+ ] }, !type !7 , !type !9
142
+
143
+ @_ZTV1D_RV = constant { [3 x i32 ] } { [3 x i32 ] [
144
+ i32 0 ,
145
+ i32 undef ,
146
+ i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1D1mEi to i64 ), i64 ptrtoint (ptr getelementptr inbounds ({ [3 x i32 ] }, ptr @_ZTV1D_RV , i32 0 , i32 0 , i32 2 ) to i64 )) to i32 )
147
+ ] }, !type !10
102
148
103
149
; CHECK-IR-LABEL: define {{(noundef )?}}i32 @test
104
150
define i32 @test (ptr %obj , ptr %obj2 , i32 %a ) {
@@ -136,6 +182,43 @@ entry:
136
182
; CHECK-IR-LABEL: ret i32
137
183
; CHECK-IR-LABEL: }
138
184
185
+ declare ptr @llvm.load.relative.i32 (ptr , i32 )
186
+
187
+ ; CHECK-IR-LABEL: define {{.*}}i32 @test_rv
188
+ define i32 @test_rv (ptr %obj , ptr %obj2 , i32 %a ) {
189
+ entry:
190
+ %vtable = load ptr , ptr %obj
191
+ %p = call i1 @llvm.type.test (ptr %vtable , metadata !"_ZTS1A_RV" )
192
+ call void @llvm.assume (i1 %p )
193
+ %fptr1_rv = call ptr @llvm.load.relative.i32 (ptr %vtable , i32 4 )
194
+
195
+ ; Check that the call was devirtualized.
196
+ ; CHECK-IR: %call = tail call i32 @_ZN1A1nEi
197
+ ; Ensure !prof and !callees metadata for indirect call promotion removed.
198
+ ; CHECK-IR-NOT: prof
199
+ ; CHECK-IR-NOT: callees
200
+ %call = tail call i32 %fptr1_rv (ptr nonnull %obj , i32 %a ), !prof !5 , !callees !6
201
+
202
+ %fptr22_rv = call ptr @llvm.load.relative.i32 (ptr %vtable , i32 0 )
203
+
204
+ ; We still have to call it as virtual.
205
+ ; CHECK-IR: %call3 = tail call i32 %fptr22
206
+ %call3 = tail call i32 %fptr22_rv (ptr nonnull %obj , i32 %call )
207
+
208
+ %vtable2 = load ptr , ptr %obj2
209
+ %p2 = call i1 @llvm.type.test (ptr %vtable2 , metadata !11 )
210
+ call void @llvm.assume (i1 %p2 )
211
+
212
+ %fptr33_rv = call ptr @llvm.load.relative.i32 (ptr %vtable2 , i32 0 )
213
+
214
+ ; Check that the call was devirtualized.
215
+ ; CHECK-IR: %call4 = tail call i32 @_ZN1D1mEi
216
+ %call4 = tail call i32 %fptr33_rv (ptr nonnull %obj2 , i32 %call3 )
217
+ ret i32 %call4
218
+ }
219
+ ; CHECK-IR-LABEL: ret i32
220
+ ; CHECK-IR-LABEL: }
221
+
139
222
declare i1 @llvm.type.test (ptr , metadata )
140
223
declare void @llvm.assume (i1 )
141
224
@@ -165,3 +248,9 @@ attributes #0 = { noinline optnone }
165
248
!4 = distinct !{}
166
249
!5 = !{!"VP" , i32 0 , i64 1 , i64 1621563287929432257 , i64 1 }
167
250
!6 = !{ptr @_ZN1A1nEi }
251
+
252
+ !7 = !{i64 8 , !"_ZTS1A_RV" }
253
+ !8 = !{i64 8 , !"_ZTS1B_RV" }
254
+ !9 = !{i64 8 , !"_ZTS1C_RV" }
255
+ !10 = !{i64 8 , !11 }
256
+ !11 = distinct !{}
0 commit comments