1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
3 ; RUN: opt < %s -passes='pgo-icall-prom' -pass-remarks=pgo-icall-prom -enable-vtable-profile-use -icp-max-num-vtable-last-candidate=2 -S 2>&1 | FileCheck %s --check-prefixes=VTABLE-COMMON,VTABLE-CMP
4 ; RUN: opt < %s -passes='pgo-icall-prom' -pass-remarks=pgo-icall-prom -enable-vtable-profile-use -icp-max-num-vtable-last-candidate=1 -S 2>&1 | FileCheck %s --check-prefixes=VTABLE-COMMON,FUNC-CMP
6 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
7 target triple = "x86_64-unknown-linux-gnu"
9 @Base1 = constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr null, ptr @Base1_foo, ptr @Base1_bar] }, !type !0
10 @Base2 = constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr @Base2_foo] }, !type !2
11 @Base3 = constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr @Base3_foo] }, !type !6
13 @Derived1 = constant { [3 x ptr], [4 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr @Base2_foo], [4 x ptr] [ptr null, ptr null, ptr @Base1_foo, ptr @Derived1_bar] }, !type !1, !type !2, !type !3
14 @Derived2 = constant { [3 x ptr], [3 x ptr], [4 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr @Base3_foo], [3 x ptr] [ptr null, ptr null, ptr @Base2_foo], [4 x ptr] [ptr null, ptr null, ptr @Base1_foo, ptr @Derived2_bar] }, !type !4, !type !5, !type !6, !type !7
15 @Derived3 = constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr null, ptr @Base1_foo, ptr @Base1_bar] }, !type !0, !type !8
17 ; VTABLE-CMP: remark: <unknown>:0:0: Promote indirect call to Derived1_bar with count 600 out of 1600, sink 2 instruction(s) and compare 1 vtable(s): {Derived1}
18 ; VTABLE-CMP: remark: <unknown>:0:0: Promote indirect call to Derived2_bar with count 500 out of 1000, sink 2 instruction(s) and compare 1 vtable(s): {Derived2}
19 ; VTABLE-CMP: remark: <unknown>:0:0: Promote indirect call to Base1_bar with count 400 out of 500, sink 2 instruction(s) and compare 2 vtable(s): {Derived3, Base1}
21 define void @test(ptr %d) {
22 ; VTABLE-CMP-LABEL: define void @test(
23 ; VTABLE-CMP-SAME: ptr [[D:%.*]]) {
24 ; VTABLE-CMP-NEXT: [[ENTRY:.*:]]
25 ; VTABLE-CMP-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[D]], align 8, !prof [[PROF9:![0-9]+]]
26 ; VTABLE-CMP-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.type.test(ptr [[VTABLE]], metadata !"Base1")
27 ; VTABLE-CMP-NEXT: tail call void @llvm.assume(i1 [[TMP0]])
28 ; VTABLE-CMP-NEXT: [[TMP1:%.*]] = icmp eq ptr [[VTABLE]], getelementptr inbounds (i8, ptr @Derived1, i32 40)
29 ; VTABLE-CMP-NEXT: br i1 [[TMP1]], label %[[IF_TRUE_DIRECT_TARG:.*]], label %[[IF_FALSE_ORIG_INDIRECT:.*]], !prof [[PROF10:![0-9]+]]
30 ; VTABLE-CMP: [[IF_TRUE_DIRECT_TARG]]:
31 ; VTABLE-CMP-NEXT: call void @Derived1_bar(ptr [[D]])
32 ; VTABLE-CMP-NEXT: br label %[[IF_END_ICP:.*]]
33 ; VTABLE-CMP: [[IF_FALSE_ORIG_INDIRECT]]:
34 ; VTABLE-CMP-NEXT: [[TMP2:%.*]] = icmp eq ptr [[VTABLE]], getelementptr inbounds (i8, ptr @Derived2, i32 64)
35 ; VTABLE-CMP-NEXT: br i1 [[TMP2]], label %[[IF_TRUE_DIRECT_TARG1:.*]], label %[[IF_FALSE_ORIG_INDIRECT2:.*]], !prof [[PROF11:![0-9]+]]
36 ; VTABLE-CMP: [[IF_TRUE_DIRECT_TARG1]]:
37 ; VTABLE-CMP-NEXT: call void @Derived2_bar(ptr [[D]])
38 ; VTABLE-CMP-NEXT: br label %[[IF_END_ICP3:.*]]
39 ; VTABLE-CMP: [[IF_FALSE_ORIG_INDIRECT2]]:
40 ; VTABLE-CMP-NEXT: [[TMP3:%.*]] = icmp eq ptr [[VTABLE]], getelementptr inbounds (i8, ptr @Base1, i32 16)
41 ; VTABLE-CMP-NEXT: [[TMP4:%.*]] = icmp eq ptr [[VTABLE]], getelementptr inbounds (i8, ptr @Derived3, i32 16)
42 ; VTABLE-CMP-NEXT: [[TMP5:%.*]] = or i1 [[TMP3]], [[TMP4]]
43 ; VTABLE-CMP-NEXT: br i1 [[TMP5]], label %[[IF_TRUE_DIRECT_TARG4:.*]], label %[[IF_FALSE_ORIG_INDIRECT5:.*]], !prof [[PROF12:![0-9]+]]
44 ; VTABLE-CMP: [[IF_TRUE_DIRECT_TARG4]]:
45 ; VTABLE-CMP-NEXT: call void @Base1_bar(ptr [[D]])
46 ; VTABLE-CMP-NEXT: br label %[[IF_END_ICP6:.*]]
47 ; VTABLE-CMP: [[IF_FALSE_ORIG_INDIRECT5]]:
48 ; VTABLE-CMP-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 1
49 ; VTABLE-CMP-NEXT: [[TMP6:%.*]] = load ptr, ptr [[VFN]], align 8
50 ; VTABLE-CMP-NEXT: call void [[TMP6]](ptr [[D]])
51 ; VTABLE-CMP-NEXT: br label %[[IF_END_ICP6]]
52 ; VTABLE-CMP: [[IF_END_ICP6]]:
53 ; VTABLE-CMP-NEXT: br label %[[IF_END_ICP3]]
54 ; VTABLE-CMP: [[IF_END_ICP3]]:
55 ; VTABLE-CMP-NEXT: br label %[[IF_END_ICP]]
56 ; VTABLE-CMP: [[IF_END_ICP]]:
57 ; VTABLE-CMP-NEXT: ret void
59 ; FUNC-CMP-LABEL: define void @test(
60 ; FUNC-CMP-SAME: ptr [[D:%.*]]) {
61 ; FUNC-CMP-NEXT: [[ENTRY:.*:]]
62 ; FUNC-CMP-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[D]], align 8, !prof [[PROF9:![0-9]+]]
63 ; FUNC-CMP-NEXT: [[TMP0:%.*]] = tail call i1 @llvm.type.test(ptr [[VTABLE]], metadata !"Base1")
64 ; FUNC-CMP-NEXT: tail call void @llvm.assume(i1 [[TMP0]])
65 ; FUNC-CMP-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 1
66 ; FUNC-CMP-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VFN]], align 8
67 ; FUNC-CMP-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP1]], @Derived1_bar
68 ; FUNC-CMP-NEXT: br i1 [[TMP2]], label %[[IF_TRUE_DIRECT_TARG:.*]], label %[[IF_FALSE_ORIG_INDIRECT:.*]], !prof [[PROF10:![0-9]+]]
69 ; FUNC-CMP: [[IF_TRUE_DIRECT_TARG]]:
70 ; FUNC-CMP-NEXT: call void @Derived1_bar(ptr [[D]])
71 ; FUNC-CMP-NEXT: br label %[[IF_END_ICP:.*]]
72 ; FUNC-CMP: [[IF_FALSE_ORIG_INDIRECT]]:
73 ; FUNC-CMP-NEXT: [[TMP3:%.*]] = icmp eq ptr [[TMP1]], @Derived2_bar
74 ; FUNC-CMP-NEXT: br i1 [[TMP3]], label %[[IF_TRUE_DIRECT_TARG1:.*]], label %[[IF_FALSE_ORIG_INDIRECT2:.*]], !prof [[PROF11:![0-9]+]]
75 ; FUNC-CMP: [[IF_TRUE_DIRECT_TARG1]]:
76 ; FUNC-CMP-NEXT: call void @Derived2_bar(ptr [[D]])
77 ; FUNC-CMP-NEXT: br label %[[IF_END_ICP3:.*]]
78 ; FUNC-CMP: [[IF_FALSE_ORIG_INDIRECT2]]:
79 ; FUNC-CMP-NEXT: [[TMP4:%.*]] = icmp eq ptr [[TMP1]], @Base1_bar
80 ; FUNC-CMP-NEXT: br i1 [[TMP4]], label %[[IF_TRUE_DIRECT_TARG4:.*]], label %[[IF_FALSE_ORIG_INDIRECT5:.*]], !prof [[PROF12:![0-9]+]]
81 ; FUNC-CMP: [[IF_TRUE_DIRECT_TARG4]]:
82 ; FUNC-CMP-NEXT: call void @Base1_bar(ptr [[D]])
83 ; FUNC-CMP-NEXT: br label %[[IF_END_ICP6:.*]]
84 ; FUNC-CMP: [[IF_FALSE_ORIG_INDIRECT5]]:
85 ; FUNC-CMP-NEXT: call void [[TMP1]](ptr [[D]])
86 ; FUNC-CMP-NEXT: br label %[[IF_END_ICP6]]
87 ; FUNC-CMP: [[IF_END_ICP6]]:
88 ; FUNC-CMP-NEXT: br label %[[IF_END_ICP3]]
89 ; FUNC-CMP: [[IF_END_ICP3]]:
90 ; FUNC-CMP-NEXT: br label %[[IF_END_ICP]]
91 ; FUNC-CMP: [[IF_END_ICP]]:
92 ; FUNC-CMP-NEXT: ret void
95 %vtable = load ptr, ptr %d, !prof !9
96 %0 = tail call i1 @llvm.type.test(ptr %vtable, metadata !"Base1")
97 tail call void @llvm.assume(i1 %0)
98 %vfn = getelementptr inbounds ptr, ptr %vtable, i64 1
99 %1 = load ptr, ptr %vfn
100 call void %1(ptr %d), !prof !10
104 define void @Base1_bar(ptr %this) {
108 define void @Derived1_bar(ptr %this) {
112 define void @Derived2_bar(ptr %this) {
117 declare i1 @llvm.type.test(ptr, metadata)
118 declare void @llvm.assume(i1)
119 declare i32 @Base2_foo(ptr)
120 declare i32 @Base1_foo(ptr)
121 declare void @Base3_foo(ptr)
123 !0 = !{i64 16, !"Base1"}
124 !1 = !{i64 40, !"Base1"}
125 !2 = !{i64 16, !"Base2"}
126 !3 = !{i64 16, !"Derived1"}
127 !4 = !{i64 64, !"Base1"}
128 !5 = !{i64 40, !"Base2"}
129 !6 = !{i64 16, !"Base3"}
130 !7 = !{i64 16, !"Derived2"}
131 !8 = !{i64 16, !"Derived3"}
132 !9 = !{!"VP", i32 2, i64 1600, i64 -4123858694673519054, i64 600, i64 -7211198353767973908, i64 500, i64 -3574436251470806727, i64 200, i64 6288809125658696740, i64 200, i64 12345678, i64 100}
133 !10 = !{!"VP", i32 0, i64 1600, i64 3827408714133779784, i64 600, i64 5837445539218476403, i64 500, i64 -9064955852395570538, i64 400, i64 56781234, i64 100}
135 ; VTABLE-COMMON: [[PROF9]] = !{!"VP", i32 2, i64 100, i64 12345678, i64 100}
136 ; VTABLE-COMMON: [[PROF10]] = !{!"branch_weights", i32 600, i32 1000}
137 ; VTABLE-COMMON: [[PROF11]] = !{!"branch_weights", i32 500, i32 500}
138 ; VTABLE-COMMON: [[PROF12]] = !{!"branch_weights", i32 400, i32 100}