1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2 ; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
4 define void @fold_nested_branch(i1 %cond1, i1 %cond2) {
5 ; CHECK-LABEL: define void @fold_nested_branch(
6 ; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]]) {
7 ; CHECK-NEXT: [[ENTRY:.*:]]
8 ; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[COND1]], [[COND2]]
9 ; CHECK-NEXT: br i1 [[TMP0]], label %[[BB4:.*]], label %[[BB3:.*]]
10 ; CHECK: [[COMMON_RET:.*]]:
11 ; CHECK-NEXT: ret void
13 ; CHECK-NEXT: call void @sideeffect1()
14 ; CHECK-NEXT: br label %[[COMMON_RET]]
16 ; CHECK-NEXT: call void @sideeffect2()
17 ; CHECK-NEXT: br label %[[COMMON_RET]]
20 br i1 %cond1, label %bb1, label %bb2
23 br i1 %cond2, label %bb3, label %bb4
26 br i1 %cond2, label %bb4, label %bb3
29 call void @sideeffect1()
33 call void @sideeffect2()
37 define void @fold_nested_branch_extra_predecessors(i1 %cond0, i1 %cond1, i1 %cond2) {
38 ; CHECK-LABEL: define void @fold_nested_branch_extra_predecessors(
39 ; CHECK-SAME: i1 [[COND0:%.*]], i1 [[COND1:%.*]], i1 [[COND2:%.*]]) {
40 ; CHECK-NEXT: [[ENTRY:.*:]]
41 ; CHECK-NEXT: br i1 [[COND0]], label %[[BB0:.*]], label %[[BB1_PRED:.*]]
42 ; CHECK: [[BB1_PRED]]:
43 ; CHECK-NEXT: call void @sideeffect1()
44 ; CHECK-NEXT: br i1 [[COND2]], label %[[BB3:.*]], label %[[BB4:.*]]
46 ; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[COND1]], [[COND2]]
47 ; CHECK-NEXT: br i1 [[TMP0]], label %[[BB4]], label %[[BB3]]
48 ; CHECK: [[COMMON_RET:.*]]:
49 ; CHECK-NEXT: ret void
51 ; CHECK-NEXT: call void @sideeffect1()
52 ; CHECK-NEXT: br label %[[COMMON_RET]]
54 ; CHECK-NEXT: call void @sideeffect2()
55 ; CHECK-NEXT: br label %[[COMMON_RET]]
58 br i1 %cond0, label %bb0, label %bb1_pred
61 call void @sideeffect1()
65 br i1 %cond1, label %bb1, label %bb2
68 br i1 %cond2, label %bb3, label %bb4
71 br i1 %cond2, label %bb4, label %bb3
74 call void @sideeffect1()
78 call void @sideeffect2()
84 define void @fold_nested_branch_cfg_mismatch(i1 %cond1, i1 %cond2) {
85 ; CHECK-LABEL: define void @fold_nested_branch_cfg_mismatch(
86 ; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]]) {
87 ; CHECK-NEXT: [[ENTRY:.*:]]
88 ; CHECK-NEXT: br i1 [[COND1]], label %[[BB1:.*]], label %[[BB2:.*]]
90 ; CHECK-NEXT: br i1 [[COND2]], label %[[BB3:.*]], label %[[COMMON_RET:.*]]
92 ; CHECK-NEXT: br i1 [[COND2]], label %[[BB4:.*]], label %[[BB3]]
93 ; CHECK: [[COMMON_RET]]:
94 ; CHECK-NEXT: ret void
96 ; CHECK-NEXT: call void @sideeffect1()
97 ; CHECK-NEXT: br label %[[COMMON_RET]]
99 ; CHECK-NEXT: call void @sideeffect2()
100 ; CHECK-NEXT: br label %[[COMMON_RET]]
103 br i1 %cond1, label %bb1, label %bb2
106 br i1 %cond2, label %bb3, label %bb5
109 br i1 %cond2, label %bb4, label %bb3
112 call void @sideeffect1()
116 call void @sideeffect2()
123 define void @fold_nested_branch_cond_mismatch(i1 %cond1, i1 %cond2, i1 %cond3) {
124 ; CHECK-LABEL: define void @fold_nested_branch_cond_mismatch(
125 ; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]], i1 [[COND3:%.*]]) {
126 ; CHECK-NEXT: [[ENTRY:.*:]]
127 ; CHECK-NEXT: br i1 [[COND1]], label %[[BB1:.*]], label %[[BB2:.*]]
129 ; CHECK-NEXT: br i1 [[COND2]], label %[[BB3:.*]], label %[[BB4:.*]]
131 ; CHECK-NEXT: br i1 [[COND3]], label %[[BB4]], label %[[BB3]]
132 ; CHECK: [[COMMON_RET:.*]]:
133 ; CHECK-NEXT: ret void
135 ; CHECK-NEXT: call void @sideeffect1()
136 ; CHECK-NEXT: br label %[[COMMON_RET]]
138 ; CHECK-NEXT: call void @sideeffect2()
139 ; CHECK-NEXT: br label %[[COMMON_RET]]
142 br i1 %cond1, label %bb1, label %bb2
145 br i1 %cond2, label %bb3, label %bb4
148 br i1 %cond3, label %bb4, label %bb3
151 call void @sideeffect1()
155 call void @sideeffect2()
159 define void @fold_nested_branch_non_trivial_succ(i1 %cond1, i1 %cond2) {
160 ; CHECK-LABEL: define void @fold_nested_branch_non_trivial_succ(
161 ; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]]) {
162 ; CHECK-NEXT: [[ENTRY:.*:]]
163 ; CHECK-NEXT: br i1 [[COND1]], label %[[BB1:.*]], label %[[BB2:.*]]
165 ; CHECK-NEXT: call void @sideeffect1()
166 ; CHECK-NEXT: br i1 [[COND2]], label %[[BB3:.*]], label %[[BB4:.*]]
168 ; CHECK-NEXT: br i1 [[COND2]], label %[[BB4]], label %[[BB3]]
169 ; CHECK: [[COMMON_RET:.*]]:
170 ; CHECK-NEXT: ret void
172 ; CHECK-NEXT: call void @sideeffect1()
173 ; CHECK-NEXT: br label %[[COMMON_RET]]
175 ; CHECK-NEXT: call void @sideeffect2()
176 ; CHECK-NEXT: br label %[[COMMON_RET]]
179 br i1 %cond1, label %bb1, label %bb2
182 call void @sideeffect1()
183 br i1 %cond2, label %bb3, label %bb4
186 br i1 %cond2, label %bb4, label %bb3
189 call void @sideeffect1()
193 call void @sideeffect2()
197 define i32 @fold_nested_branch_with_phi(i1 %cond1, i1 %cond2, i32 %x) {
198 ; CHECK-LABEL: define i32 @fold_nested_branch_with_phi(
199 ; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]], i32 [[X:%.*]]) {
200 ; CHECK-NEXT: [[ENTRY:.*:]]
201 ; CHECK-NEXT: br i1 [[COND1]], label %[[BB1:.*]], label %[[BB2:.*]]
203 ; CHECK-NEXT: br i1 [[COND2]], label %[[COMMON_RET:.*]], label %[[BB4:.*]]
205 ; CHECK-NEXT: br i1 [[COND2]], label %[[BB4]], label %[[COMMON_RET]]
206 ; CHECK: [[COMMON_RET]]:
207 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 0, %[[BB4]] ], [ 0, %[[BB1]] ], [ [[X]], %[[BB2]] ]
208 ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
210 ; CHECK-NEXT: call void @sideeffect2()
211 ; CHECK-NEXT: br label %[[COMMON_RET]]
214 br i1 %cond1, label %bb1, label %bb2
217 br i1 %cond2, label %bb3, label %bb4
220 br i1 %cond2, label %bb4, label %bb3
223 %ret = phi i32 [ 0, %bb1 ], [ %x, %bb2 ]
227 call void @sideeffect2()
231 define void @fold_nested_branch_loop1(i1 %cond1, i1 %cond2) {
232 ; CHECK-LABEL: define void @fold_nested_branch_loop1(
233 ; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]]) {
234 ; CHECK-NEXT: [[ENTRY:.*:]]
235 ; CHECK-NEXT: [[COND1_NOT:%.*]] = xor i1 [[COND1]], true
236 ; CHECK-NEXT: [[BRMERGE:%.*]] = select i1 [[COND1_NOT]], i1 true, i1 [[COND2]]
237 ; CHECK-NEXT: br i1 [[BRMERGE]], label %[[BB3:.*]], label %[[BB4:.*]]
238 ; CHECK: [[COMMON_RET:.*]]:
239 ; CHECK-NEXT: ret void
241 ; CHECK-NEXT: call void @sideeffect1()
242 ; CHECK-NEXT: br label %[[COMMON_RET]]
244 ; CHECK-NEXT: call void @sideeffect2()
245 ; CHECK-NEXT: br label %[[COMMON_RET]]
248 br i1 %cond1, label %bb1, label %bb2
251 br i1 %cond2, label %bb3, label %bb4
254 br i1 %cond2, label %bb1, label %bb3
257 call void @sideeffect1()
261 call void @sideeffect2()
265 define void @fold_nested_branch_loop2(i1 %cond1, i1 %cond2) {
266 ; CHECK-LABEL: define void @fold_nested_branch_loop2(
267 ; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]]) {
268 ; CHECK-NEXT: [[ENTRY:.*:]]
269 ; CHECK-NEXT: br label %[[BB0:.*]]
271 ; CHECK-NEXT: br i1 [[COND1]], label %[[BB1:.*]], label %[[BB2:.*]]
273 ; CHECK-NEXT: br i1 [[COND2]], label %[[BB3:.*]], label %[[BB4:.*]]
275 ; CHECK-NEXT: br i1 [[COND2]], label %[[BB0]], label %[[BB3]]
276 ; CHECK: [[COMMON_RET:.*]]:
277 ; CHECK-NEXT: ret void
279 ; CHECK-NEXT: call void @sideeffect1()
280 ; CHECK-NEXT: br label %[[COMMON_RET]]
282 ; CHECK-NEXT: call void @sideeffect2()
283 ; CHECK-NEXT: br label %[[COMMON_RET]]
289 br i1 %cond1, label %bb1, label %bb2
292 br i1 %cond2, label %bb3, label %bb4
295 br i1 %cond2, label %bb0, label %bb3
298 call void @sideeffect1()
302 call void @sideeffect2()
306 ; Make sure that branch weights are correctly preserved
307 ; freq(bb4) = 1 * 4 + 2 * 5 = 14
308 ; freq(bb3) = 1 * 3 + 2 * 6 = 15
309 define void @fold_nested_branch_prof(i1 %cond1, i1 %cond2) {
310 ; CHECK-LABEL: define void @fold_nested_branch_prof(
311 ; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]]) {
312 ; CHECK-NEXT: [[ENTRY:.*:]]
313 ; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[COND1]], [[COND2]]
314 ; CHECK-NEXT: br i1 [[TMP0]], label %[[BB4:.*]], label %[[BB3:.*]], !prof [[PROF0:![0-9]+]]
315 ; CHECK: [[COMMON_RET:.*]]:
316 ; CHECK-NEXT: ret void
318 ; CHECK-NEXT: call void @sideeffect1()
319 ; CHECK-NEXT: br label %[[COMMON_RET]]
321 ; CHECK-NEXT: call void @sideeffect2()
322 ; CHECK-NEXT: br label %[[COMMON_RET]]
325 br i1 %cond1, label %bb1, label %bb2, !prof !0 ; 1:2
328 br i1 %cond2, label %bb3, label %bb4, !prof !1 ; 3:4
331 br i1 %cond2, label %bb4, label %bb3, !prof !2 ; 5:6
334 call void @sideeffect1()
338 call void @sideeffect2()
342 !0 = !{!"branch_weights", i32 1, i32 2}
343 !1 = !{!"branch_weights", i32 3, i32 4}
344 !2 = !{!"branch_weights", i32 5, i32 6}
347 declare void @sideeffect1()
348 declare void @sideeffect2()
350 ; CHECK: [[PROF0]] = !{!"branch_weights", i32 14, i32 15}