xref: /llvm-project/llvm/test/Transforms/LowerExpectIntrinsic/phi_unexpect.ll (revision 294f3ce5dde916c358d8f672b4a1c706c0387154)
1; RUN: opt -S -passes='function(lower-expect),strip-dead-prototypes' -likely-branch-weight=2147483647 -unlikely-branch-weight=1 < %s | FileCheck %s
2
3; The C case
4; if (__builtin_expect_with_probability(((a0 == 1) || (a1 == 1) || (a2 == 1)), 1, 0))
5; For the above case, all 3 branches should be annotated
6; which should be equivalent to if (__builtin_expect(((a0 == 1) || (a1 == 1) || (a2 == 1)), 0))
7
8; The C case
9; if (__builtin_expect_with_probability(((a0 == 1) || (a1 == 1) || (a2 == 1)), 1, 1))
10; For the above case, we do not have enough information, so only the last branch could be annotated
11; which should be equivalent to if (__builtin_expect(((a0 == 1) || (a1 == 1) || (a2 == 1)), 1))
12
13declare void @foo()
14
15declare i64 @llvm.expect.i64(i64, i64) nounwind readnone
16declare i64 @llvm.expect.with.probability.i64(i64, i64, double) nounwind readnone
17
18; CHECK-LABEL: @test1_expect_1(
19; CHECK: block0:
20; CHECK-NOT: prof
21; CHECK: block1:
22; CHECK-NOT: prof
23; CHECK: block3:
24; CHECK: br i1 %tobool, label %block4, label %block5, !prof !0
25define void @test1_expect_1(i8 %a0, i8 %a1, i8 %a2) {
26block0:
27  %c0 = icmp eq i8 %a0, 1
28  br i1 %c0, label %block3, label %block1
29
30block1:
31  %c1 = icmp eq i8 %a1, 1
32  br i1 %c1, label %block3, label %block2
33
34block2:
35  %c2 = icmp eq i8 %a2, 1
36  br label %block3
37
38block3:
39  %cond0 = phi i1 [ true, %block0 ], [ true, %block1 ], [ %c2, %block2 ]
40  %cond1 = zext i1 %cond0 to i32
41  %cond2 = sext i32 %cond1 to i64
42  %expval = call i64 @llvm.expect.i64(i64 %cond2, i64 1)
43  %tobool = icmp ne i64 %expval, 0
44  br i1 %tobool, label %block4, label %block5
45
46block4:
47  call void @foo()
48  br label %block5
49
50block5:
51  ret void
52}
53
54; should have exactly the same behavior as test1
55; CHECK-LABEL: @test2_expect_with_prob_1_1(
56; CHECK: block0:
57; CHECK-NOT: prof
58; CHECK: block1:
59; CHECK-NOT: prof
60; CHECK: block3:
61; CHECK: br i1 %tobool, label %block4, label %block5, !prof !0
62define void @test2_expect_with_prob_1_1(i8 %a0, i8 %a1, i8 %a2) {
63block0:
64  %c0 = icmp eq i8 %a0, 1
65  br i1 %c0, label %block3, label %block1
66
67block1:
68  %c1 = icmp eq i8 %a1, 1
69  br i1 %c1, label %block3, label %block2
70
71block2:
72  %c2 = icmp eq i8 %a2, 1
73  br label %block3
74
75block3:
76  %cond0 = phi i1 [ true, %block0 ], [ true, %block1 ], [ %c2, %block2 ]
77  %cond1 = zext i1 %cond0 to i32
78  %cond2 = sext i32 %cond1 to i64
79  %expval = call i64 @llvm.expect.with.probability.i64(i64 %cond2, i64 1, double 1.0)
80  %tobool = icmp ne i64 %expval, 0
81  br i1 %tobool, label %block4, label %block5
82
83block4:
84  call void @foo()
85  br label %block5
86
87block5:
88  ret void
89}
90
91; should have exactly the same behavior as test1
92; CHECK-LABEL: @test3_expect_with_prob_0_0(
93; CHECK: block0:
94; CHECK-NOT: prof
95; CHECK: block1:
96; CHECK-NOT: prof
97; CHECK: block3:
98; CHECK: br i1 %tobool, label %block4, label %block5, !prof !0
99define void @test3_expect_with_prob_0_0(i8 %a0, i8 %a1, i8 %a2) {
100block0:
101  %c0 = icmp eq i8 %a0, 1
102  br i1 %c0, label %block3, label %block1
103
104block1:
105  %c1 = icmp eq i8 %a1, 1
106  br i1 %c1, label %block3, label %block2
107
108block2:
109  %c2 = icmp eq i8 %a2, 1
110  br label %block3
111
112block3:
113  %cond0 = phi i1 [ true, %block0 ], [ true, %block1 ], [ %c2, %block2 ]
114  %cond1 = zext i1 %cond0 to i32
115  %cond2 = sext i32 %cond1 to i64
116  %expval = call i64 @llvm.expect.with.probability.i64(i64 %cond2, i64 0, double 0.0)
117  %tobool = icmp ne i64 %expval, 0
118  br i1 %tobool, label %block4, label %block5
119
120block4:
121  call void @foo()
122  br label %block5
123
124block5:
125  ret void
126}
127
128; CHECK-LABEL: @test4_expect_0(
129; CHECK: block0:
130; CHECK: br i1 %c0, label %block3, label %block1, !prof !1
131; CHECK: block1:
132; CHECK: br i1 %c1, label %block3, label %block2, !prof !1
133; CHECK: block3:
134; CHECK: br i1 %tobool, label %block4, label %block5, !prof !1
135define void @test4_expect_0(i8 %a0, i8 %a1, i8 %a2) {
136block0:
137  %c0 = icmp eq i8 %a0, 1
138  br i1 %c0, label %block3, label %block1
139
140block1:
141  %c1 = icmp eq i8 %a1, 1
142  br i1 %c1, label %block3, label %block2
143
144block2:
145  %c2 = icmp eq i8 %a2, 1
146  br label %block3
147
148block3:
149  %cond0 = phi i1 [ true, %block0 ], [ true, %block1 ], [ %c2, %block2 ]
150  %cond1 = zext i1 %cond0 to i32
151  %cond2 = sext i32 %cond1 to i64
152  %expval = call i64 @llvm.expect.i64(i64 %cond2, i64 0)
153  %tobool = icmp ne i64 %expval, 0
154  br i1 %tobool, label %block4, label %block5
155
156block4:
157  call void @foo()
158  br label %block5
159
160block5:
161  ret void
162}
163
164; should have exactly the same behavior as test4
165; CHECK-LABEL: @test5_expect_with_prob_1_0(
166; CHECK: block0:
167; CHECK: br i1 %c0, label %block3, label %block1, !prof !1
168; CHECK: block1:
169; CHECK: br i1 %c1, label %block3, label %block2, !prof !1
170; CHECK: block3:
171; CHECK: br i1 %tobool, label %block4, label %block5, !prof !1
172define void @test5_expect_with_prob_1_0(i8 %a0, i8 %a1, i8 %a2) {
173block0:
174  %c0 = icmp eq i8 %a0, 1
175  br i1 %c0, label %block3, label %block1
176
177block1:
178  %c1 = icmp eq i8 %a1, 1
179  br i1 %c1, label %block3, label %block2
180
181block2:
182  %c2 = icmp eq i8 %a2, 1
183  br label %block3
184
185block3:
186  %cond0 = phi i1 [ true, %block0 ], [ true, %block1 ], [ %c2, %block2 ]
187  %cond1 = zext i1 %cond0 to i32
188  %cond2 = sext i32 %cond1 to i64
189  %expval = call i64 @llvm.expect.with.probability.i64(i64 %cond2, i64 1, double 0.0)
190  %tobool = icmp ne i64 %expval, 0
191  br i1 %tobool, label %block4, label %block5
192
193block4:
194  call void @foo()
195  br label %block5
196
197block5:
198  ret void
199}
200
201; should have exactly the same behavior as test4
202; CHECK-LABEL: @test6_expect_with_prob_0_1(
203; CHECK: block0:
204; CHECK: br i1 %c0, label %block3, label %block1, !prof !1
205; CHECK: block1:
206; CHECK: br i1 %c1, label %block3, label %block2, !prof !1
207; CHECK: block3:
208; CHECK: br i1 %tobool, label %block4, label %block5, !prof !1
209define void @test6_expect_with_prob_0_1(i8 %a0, i8 %a1, i8 %a2) {
210block0:
211  %c0 = icmp eq i8 %a0, 1
212  br i1 %c0, label %block3, label %block1
213
214block1:
215  %c1 = icmp eq i8 %a1, 1
216  br i1 %c1, label %block3, label %block2
217
218block2:
219  %c2 = icmp eq i8 %a2, 1
220  br label %block3
221
222block3:
223  %cond0 = phi i1 [ true, %block0 ], [ true, %block1 ], [ %c2, %block2 ]
224  %cond1 = zext i1 %cond0 to i32
225  %cond2 = sext i32 %cond1 to i64
226  %expval = call i64 @llvm.expect.with.probability.i64(i64 %cond2, i64 0, double 1.0)
227  %tobool = icmp ne i64 %expval, 0
228  br i1 %tobool, label %block4, label %block5
229
230block4:
231  call void @foo()
232  br label %block5
233
234block5:
235  ret void
236}
237
238; CHECK: !0 = !{!"branch_weights", !"expected", i32 2147483647, i32 1}
239; CHECK: !1 = !{!"branch_weights", !"expected", i32 1, i32 2147483647}
240