5
5
// ld.lld: error: /lib/../lib64/Scrt1.o: ABI version 1 is not supported
6
6
// UNSUPPORTED: ppc && host-byteorder-big-endian
7
7
8
- // RUN: %clangxx_pgogen -fuse-ld=lld -O2 -g -fprofile-generate=. -mllvm -enable-vtable-value-profiling %s -o %t-test
9
- // RUN: env LLVM_PROFILE_FILE=%t-test.profraw %t-test
8
+ // RUN: rm -rf %t && mkdir %t && cd %t
9
+
10
+ // RUN: %clangxx_pgogen -fuse-ld=lld -O2 -fprofile-generate=. -mllvm -enable-vtable-value-profiling %s -o test
11
+ // RUN: env LLVM_PROFILE_FILE=test.profraw ./test
10
12
11
13
// Show vtable profiles from raw profile.
12
- // RUN: llvm-profdata show --function=main --ic-targets --show-vtables %t- test.profraw | FileCheck %s --check-prefixes=COMMON,RAW
14
+ // RUN: llvm-profdata show --function=main --ic-targets --show-vtables test.profraw | FileCheck %s --check-prefixes=COMMON,RAW
13
15
14
16
// Generate indexed profile from raw profile and show the data.
15
- // RUN: llvm-profdata merge --keep-vtable-symbols %t- test.profraw -o %t- test.profdata
16
- // RUN: llvm-profdata show --function=main --ic-targets --show-vtables %t- test.profdata | FileCheck %s --check-prefixes=COMMON,INDEXED
17
+ // RUN: llvm-profdata merge --keep-vtable-symbols test.profraw -o test.profdata
18
+ // RUN: llvm-profdata show --function=main --ic-targets --show-vtables test.profdata | FileCheck %s --check-prefixes=COMMON,INDEXED
17
19
18
20
// Generate text profile from raw and indexed profiles respectively and show the data.
19
- // RUN: llvm-profdata merge --keep-vtable-symbols --text %t- test.profraw -o %t- raw.proftext
20
- // RUN: llvm-profdata show --function=main --ic-targets --show-vtables --text %t- raw.proftext | FileCheck %s --check-prefix=ICTEXT
21
- // RUN: llvm-profdata merge --keep-vtable-symbols --text %t- test.profdata -o %t- indexed.proftext
22
- // RUN: llvm-profdata show --function=main --ic-targets --show-vtables --text %t- indexed.proftext | FileCheck %s --check-prefix=ICTEXT
21
+ // RUN: llvm-profdata merge --keep-vtable-symbols --text test.profraw -o raw.proftext
22
+ // RUN: llvm-profdata show --function=main --ic-targets --show-vtables --text raw.proftext | FileCheck %s --check-prefix=ICTEXT
23
+ // RUN: llvm-profdata merge --keep-vtable-symbols --text test.profdata -o indexed.proftext
24
+ // RUN: llvm-profdata show --function=main --ic-targets --show-vtables --text indexed.proftext | FileCheck %s --check-prefix=ICTEXT
23
25
24
26
// Generate indexed profile from text profiles and show the data
25
- // RUN: llvm-profdata merge --keep-vtable-symbols --binary %t- raw.proftext -o %t- text.profraw
26
- // RUN: llvm-profdata show --function=main --ic-targets --show-vtables %t- text.profraw | FileCheck %s --check-prefixes=COMMON,INDEXED
27
- // RUN: llvm-profdata merge --keep-vtable-symbols --binary %t- indexed.proftext -o %t- text.profdata
28
- // RUN: llvm-profdata show --function=main --ic-targets --show-vtables %t- text.profdata | FileCheck %s --check-prefixes=COMMON,INDEXED
27
+ // RUN: llvm-profdata merge --keep-vtable-symbols --binary raw.proftext -o text.profraw
28
+ // RUN: llvm-profdata show --function=main --ic-targets --show-vtables text.profraw | FileCheck %s --check-prefixes=COMMON,INDEXED
29
+ // RUN: llvm-profdata merge --keep-vtable-symbols --binary indexed.proftext -o text.profdata
30
+ // RUN: llvm-profdata show --function=main --ic-targets --show-vtables text.profdata | FileCheck %s --check-prefixes=COMMON,INDEXED
29
31
30
32
// COMMON: Counters:
31
33
// COMMON-NEXT: main:
32
- // COMMON-NEXT: Hash: 0x0f9a16fe6d398548
33
- // COMMON-NEXT: Counters: 2
34
+ // COMMON-NEXT: Hash: 0x068617320ec408a0
35
+ // COMMON-NEXT: Counters: 4
34
36
// COMMON-NEXT: Indirect Call Site Count: 2
35
37
// COMMON-NEXT: Number of instrumented vtables: 2
36
38
// RAW: Indirect Target Results:
37
- // RAW-NEXT: [ 0, _ZN8Derived15func1Eii , 250 ] (25.00%)
38
- // RAW-NEXT: [ 0, {{.*}}instrprof-vtable-value-prof.cpp;_ZN12_GLOBAL__N_18Derived25func1Eii , 750 ] (75.00%)
39
- // RAW-NEXT: [ 1, _ZN8Derived15func2Eii , 250 ] (25.00%)
40
- // RAW-NEXT: [ 1, {{.*}}instrprof-vtable-value-prof.cpp;_ZN12_GLOBAL__N_18Derived25func2Eii , 750 ] (75.00%)
39
+ // RAW-NEXT: [ 0, _ZN8Derived14funcEii , 50 ] (25.00%)
40
+ // RAW-NEXT: [ 0, {{.*}}instrprof-vtable-value-prof.cpp;_ZN12_GLOBAL__N_18Derived24funcEii , 150 ] (75.00%)
41
+ // RAW-NEXT: [ 1, _ZN8Derived1D0Ev , 250 ] (25.00%)
42
+ // RAW-NEXT: [ 1, {{.*}}instrprof-vtable-value-prof.cpp;_ZN12_GLOBAL__N_18Derived2D0Ev , 750 ] (75.00%)
41
43
// RAW-NEXT: VTable Results:
42
- // RAW-NEXT: [ 0, _ZTV8Derived1, 250 ] (25.00%)
43
- // RAW-NEXT: [ 0, {{.*}}instrprof-vtable-value-prof.cpp;_ZTVN12_GLOBAL__N_18Derived2E, 750 ] (75.00%)
44
+ // RAW-NEXT: [ 0, _ZTV8Derived1, 50 ] (25.00%)
45
+ // RAW-NEXT: [ 0, {{.*}}instrprof-vtable-value-prof.cpp;_ZTVN12_GLOBAL__N_18Derived2E, 150 ] (75.00%)
44
46
// RAW-NEXT: [ 1, _ZTV8Derived1, 250 ] (25.00%)
45
47
// RAW-NEXT: [ 1, {{.*}}instrprof-vtable-value-prof.cpp;_ZTVN12_GLOBAL__N_18Derived2E, 750 ] (75.00%)
46
48
// INDEXED: Indirect Target Results:
47
- // INDEXED-NEXT: [ 0, {{.*}}instrprof-vtable-value-prof.cpp;_ZN12_GLOBAL__N_18Derived25func1Eii , 750 ] (75.00%)
48
- // INDEXED-NEXT: [ 0, _ZN8Derived15func1Eii , 250 ] (25.00%)
49
- // INDEXED-NEXT: [ 1, {{.*}}instrprof-vtable-value-prof.cpp;_ZN12_GLOBAL__N_18Derived25func2Eii , 750 ] (75.00%)
50
- // INDEXED-NEXT: [ 1, _ZN8Derived15func2Eii , 250 ] (25.00%)
49
+ // INDEXED-NEXT: [ 0, {{.*}}instrprof-vtable-value-prof.cpp;_ZN12_GLOBAL__N_18Derived24funcEii , 150 ] (75.00%)
50
+ // INDEXED-NEXT: [ 0, _ZN8Derived14funcEii , 50 ] (25.00%)
51
+ // INDEXED-NEXT: [ 1, {{.*}}instrprof-vtable-value-prof.cpp;_ZN12_GLOBAL__N_18Derived2D0Ev , 750 ] (75.00%)
52
+ // INDEXED-NEXT: [ 1, _ZN8Derived1D0Ev , 250 ] (25.00%)
51
53
// INDEXED-NEXT: VTable Results:
52
- // INDEXED-NEXT: [ 0, {{.*}}instrprof-vtable-value-prof.cpp;_ZTVN12_GLOBAL__N_18Derived2E, 750 ] (75.00%)
53
- // INDEXED-NEXT: [ 0, _ZTV8Derived1, 250 ] (25.00%)
54
+ // INDEXED-NEXT: [ 0, {{.*}}instrprof-vtable-value-prof.cpp;_ZTVN12_GLOBAL__N_18Derived2E, 150 ] (75.00%)
55
+ // INDEXED-NEXT: [ 0, _ZTV8Derived1, 50 ] (25.00%)
54
56
// INDEXED-NEXT: [ 1, {{.*}}instrprof-vtable-value-prof.cpp;_ZTVN12_GLOBAL__N_18Derived2E, 750 ] (75.00%)
55
57
// INDEXED-NEXT: [ 1, _ZTV8Derived1, 250 ] (25.00%)
56
58
// COMMON: Instrumentation level: IR entry_first = 0
57
59
// COMMON-NEXT: Functions shown: 1
58
- // COMMON-NEXT: Total functions: 6
60
+ // COMMON-NEXT: Total functions: 7
59
61
// COMMON-NEXT: Maximum function count: 1000
60
- // COMMON-NEXT: Maximum internal block count: 250
62
+ // COMMON-NEXT: Maximum internal block count: 1000
61
63
// COMMON-NEXT: Statistics for indirect call sites profile:
62
64
// COMMON-NEXT: Total number of sites: 2
63
65
// COMMON-NEXT: Total number of sites with values: 2
76
78
// ICTEXT: :ir
77
79
// ICTEXT: main
78
80
// ICTEXT: # Func Hash:
79
- // ICTEXT: 1124236338992350536
81
+ // ICTEXT: 470088714870327456
80
82
// ICTEXT: # Num Counters:
81
- // ICTEXT: 2
83
+ // ICTEXT: 4
82
84
// ICTEXT: # Counter Values:
83
85
// ICTEXT: 1000
86
+ // ICTEXT: 1000
87
+ // ICTEXT: 200
84
88
// ICTEXT: 1
85
89
// ICTEXT: # Num Value Kinds:
86
90
// ICTEXT: 2
89
93
// ICTEXT: # NumValueSites:
90
94
// ICTEXT: 2
91
95
// ICTEXT: 2
92
- // ICTEXT: {{.*}}instrprof-vtable-value-prof.cpp;_ZN12_GLOBAL__N_18Derived25func1Eii:750
93
- // ICTEXT: _ZN8Derived15func1Eii:250
96
+ // ICTEXT: {{.*}}instrprof-vtable-value-prof.cpp;_ZN12_GLOBAL__N_18Derived24funcEii:150
97
+ // ICTEXT: _ZN8Derived14funcEii:50
94
98
// ICTEXT: 2
95
- // ICTEXT: {{.*}}instrprof-vtable-value-prof.cpp;_ZN12_GLOBAL__N_18Derived25func2Eii :750
96
- // ICTEXT: _ZN8Derived15func2Eii :250
99
+ // ICTEXT: {{.*}}instrprof-vtable-value-prof.cpp;_ZN12_GLOBAL__N_18Derived2D0Ev :750
100
+ // ICTEXT: _ZN8Derived1D0Ev :250
97
101
// ICTEXT: # ValueKind = IPVK_VTableTarget:
98
102
// ICTEXT: 2
99
103
// ICTEXT: # NumValueSites:
100
104
// ICTEXT: 2
101
105
// ICTEXT: 2
102
- // ICTEXT: {{.*}}instrprof-vtable-value-prof.cpp;_ZTVN12_GLOBAL__N_18Derived2E:750
103
- // ICTEXT: _ZTV8Derived1:250
106
+ // ICTEXT: {{.*}}instrprof-vtable-value-prof.cpp;_ZTVN12_GLOBAL__N_18Derived2E:150
107
+ // ICTEXT: _ZTV8Derived1:50
104
108
// ICTEXT: 2
105
109
// ICTEXT: {{.*}}instrprof-vtable-value-prof.cpp;_ZTVN12_GLOBAL__N_18Derived2E:750
106
110
// ICTEXT: _ZTV8Derived1:250
107
111
112
+ // Test indirect call promotion transformation using vtable profiles.
113
+ // - Build with `-g` to enable debug information.
114
+ // - In real world settings, ICP pass is disabled in prelink pipeline. In
115
+ // the postlink pipeline, ICP is enabled after whole-program-devirtualization
116
+ // pass. Do the same thing in this test.
117
+ // - Enable `-fwhole-program-vtables` generate type metadata and intrinsics.
118
+ // - Enable `-fno-split-lto-unit` and `-Wl,-lto-whole-program-visibility` to
119
+ // preserve type intrinsics for ICP pass.
120
+ // RUN: %clangxx -m64 -fprofile-use=test.profdata -Wl,--lto-whole-program-visibility \
121
+ // RUN: -mllvm -disable-icp=true -Wl,-mllvm,-disable-icp=false -fuse-ld=lld \
122
+ // RUN: -g -flto=thin -fwhole-program-vtables -fno-split-lto-unit -O2 \
123
+ // RUN: -mllvm -enable-vtable-value-profiling -Wl,-mllvm,-enable-vtable-value-profiling \
124
+ // RUN: -mllvm -enable-vtable-profile-use \
125
+ // RUN: -Wl,-mllvm,-enable-vtable-profile-use -Rpass=pgo-icall-prom \
126
+ // RUN: -Wl,-mllvm,-print-after=pgo-icall-prom \
127
+ // RUN: -Wl,-mllvm,-filter-print-funcs=main %s 2>&1 \
128
+ // RUN: | FileCheck %s --check-prefixes=REMARK,IR --implicit-check-not="!VP"
129
+
130
+ // For the indirect call site `ptr->func`
131
+ // REMARK: instrprof-vtable-value-prof.cpp:205:19: Promote indirect call to _ZN12_GLOBAL__N_18Derived24funcEii with count 150 out of 200, sink 1 instruction(s) and compare 1 vtable(s): {_ZTVN12_GLOBAL__N_18Derived2E}
132
+ // REMARK: instrprof-vtable-value-prof.cpp:205:19: Promote indirect call to _ZN8Derived14funcEii with count 50 out of 50, sink 1 instruction(s) and compare 1 vtable(s): {_ZTV8Derived1}
133
+ //
134
+ // For the indirect call site `delete ptr`
135
+ // REMARK: instrprof-vtable-value-prof.cpp:207:5: Promote indirect call to _ZN12_GLOBAL__N_18Derived2D0Ev with count 750 out of 1000, sink 2 instruction(s) and compare 1 vtable(s): {_ZTVN12_GLOBAL__N_18Derived2E}
136
+ // REMARK: instrprof-vtable-value-prof.cpp:207:5: Promote indirect call to _ZN8Derived1D0Ev with count 250 out of 250, sink 2 instruction(s) and compare 1 vtable(s): {_ZTV8Derived1}
137
+
138
+ // The IR matchers for indirect callsite `ptr->func`.
139
+ // IR-LABEL: @main
140
+ // IR: [[OBJ:%.*]] = {{.*}}call {{.*}} @_Z10createTypei
141
+ // IR: [[VTABLE:%.*]] = load ptr, ptr [[OBJ]]
142
+ // IR: [[CMP1:%.*]] = icmp eq ptr [[VTABLE]], getelementptr inbounds (i8, ptr @_ZTVN12_GLOBAL__N_18Derived2E, i32 16)
143
+ // IR: br i1 [[CMP1]], label %[[BB1:.*]], label %[[BB2:[a-zA-Z0-9_.]+]],
144
+ //
145
+ // IR: [[BB1]]:
146
+ // IR: [[RESBB1:%.*]] = {{.*}}call {{.*}} @_ZN12_GLOBAL__N_18Derived24funcEii
147
+ // IR: br label %[[MERGE0:[a-zA-Z0-9_.]+]]
148
+ //
149
+ // IR: [[BB2]]:
150
+ // IR: [[CMP2:%.*]] = icmp eq ptr [[VTABLE]], getelementptr inbounds (i8, ptr @_ZTV8Derived1, i32 16)
151
+ // IR: br i1 [[CMP2]], label %[[BB3:.*]], label %[[BB4:[a-zA-Z0-9_.]+]],
152
+ //
153
+ // IR: [[BB3]]:
154
+ // IR: [[RESBB3:%.*]] = {{.*}}call {{.*}} @_ZN8Derived14funcEii
155
+ // IR: br label %[[MERGE1:[a-zA-Z0-9_.]+]],
156
+ //
157
+ // IR: [[BB4]]:
158
+ // IR: [[FUNCPTR:%.*]] = load ptr, ptr [[VTABLE]]
159
+ // IR: [[RESBB4:%.*]] = {{.*}}call {{.*}} [[FUNCPTR]]
160
+ // IR: br label %[[MERGE1]]
161
+ //
162
+ // IR: [[MERGE1]]:
163
+ // IR: [[RES1:%.*]] = phi i32 [ [[RESBB4]], %[[BB4]] ], [ [[RESBB3]], %[[BB3]] ]
164
+ // IR: br label %[[MERGE0]]
165
+ //
166
+ // IR: [[MERGE0]]:
167
+ // IR: [[RES2:%.*]] = phi i32 [ [[RES1]], %[[MERGE1]] ], [ [[RESBB1]], %[[BB1]] ]
108
168
#include < cstdio>
109
169
#include < cstdlib>
110
170
class Base {
111
171
public:
112
- virtual int func1 (int a, int b) = 0;
113
- virtual int func2 (int a, int b) = 0;
172
+ virtual int func (int a, int b) = 0;
173
+
174
+ virtual ~Base () {};
114
175
};
115
176
class Derived1 : public Base {
116
177
public:
117
- int func1 (int a, int b) override { return a + b; }
178
+ int func (int a, int b) override { return a * b; }
118
179
119
- int func2 ( int a, int b) override { return a * b; }
180
+ ~Derived1 () { }
120
181
};
121
182
namespace {
122
183
class Derived2 : public Base {
123
184
public:
124
- int func1 (int a, int b) override { return a - b; }
185
+ int func (int a, int b) override { return a * (a - b) ; }
125
186
126
- int func2 ( int a, int b) override { return a * (a - b); }
187
+ ~Derived2 () { }
127
188
};
128
189
} // namespace
129
190
__attribute__ ((noinline)) Base *createType(int a) {
@@ -140,7 +201,10 @@ int main(int argc, char **argv) {
140
201
int a = rand ();
141
202
int b = rand ();
142
203
Base *ptr = createType (i);
143
- sum += ptr->func1 (a, b) + ptr->func2 (b, a);
204
+ if (i % 5 == 0 )
205
+ sum += ptr->func (b, a);
206
+
207
+ delete ptr;
144
208
}
145
209
printf (" sum is %d\n " , sum);
146
210
return 0 ;
0 commit comments