xref: /llvm-project/llvm/test/Transforms/SimplifyCFG/branch-nested.ll (revision 4997af98a008e71a3df61707559710d1c2769839)
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
3
4define 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
12; CHECK:       [[BB3]]:
13; CHECK-NEXT:    call void @sideeffect1()
14; CHECK-NEXT:    br label %[[COMMON_RET]]
15; CHECK:       [[BB4]]:
16; CHECK-NEXT:    call void @sideeffect2()
17; CHECK-NEXT:    br label %[[COMMON_RET]]
18;
19entry:
20  br i1 %cond1, label %bb1, label %bb2
21
22bb1:
23  br i1 %cond2, label %bb3, label %bb4
24
25bb2:
26  br i1 %cond2, label %bb4, label %bb3
27
28bb3:
29  call void @sideeffect1()
30  ret void
31
32bb4:
33  call void @sideeffect2()
34  ret void
35}
36
37define 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:.*]]
45; CHECK:       [[BB0]]:
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
50; CHECK:       [[BB3]]:
51; CHECK-NEXT:    call void @sideeffect1()
52; CHECK-NEXT:    br label %[[COMMON_RET]]
53; CHECK:       [[BB4]]:
54; CHECK-NEXT:    call void @sideeffect2()
55; CHECK-NEXT:    br label %[[COMMON_RET]]
56;
57entry:
58  br i1 %cond0, label %bb0, label %bb1_pred
59
60bb1_pred:
61  call void @sideeffect1()
62  br label %bb1
63
64bb0:
65  br i1 %cond1, label %bb1, label %bb2
66
67bb1:
68  br i1 %cond2, label %bb3, label %bb4
69
70bb2:
71  br i1 %cond2, label %bb4, label %bb3
72
73bb3:
74  call void @sideeffect1()
75  ret void
76
77bb4:
78  call void @sideeffect2()
79  ret void
80}
81
82; Negative tests
83
84define 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:.*]]
89; CHECK:       [[BB1]]:
90; CHECK-NEXT:    br i1 [[COND2]], label %[[BB3:.*]], label %[[COMMON_RET:.*]]
91; CHECK:       [[BB2]]:
92; CHECK-NEXT:    br i1 [[COND2]], label %[[BB4:.*]], label %[[BB3]]
93; CHECK:       [[COMMON_RET]]:
94; CHECK-NEXT:    ret void
95; CHECK:       [[BB3]]:
96; CHECK-NEXT:    call void @sideeffect1()
97; CHECK-NEXT:    br label %[[COMMON_RET]]
98; CHECK:       [[BB4]]:
99; CHECK-NEXT:    call void @sideeffect2()
100; CHECK-NEXT:    br label %[[COMMON_RET]]
101;
102entry:
103  br i1 %cond1, label %bb1, label %bb2
104
105bb1:
106  br i1 %cond2, label %bb3, label %bb5
107
108bb2:
109  br i1 %cond2, label %bb4, label %bb3
110
111bb3:
112  call void @sideeffect1()
113  ret void
114
115bb4:
116  call void @sideeffect2()
117  ret void
118
119bb5:
120  ret void
121}
122
123define 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:.*]]
128; CHECK:       [[BB1]]:
129; CHECK-NEXT:    br i1 [[COND2]], label %[[BB3:.*]], label %[[BB4:.*]]
130; CHECK:       [[BB2]]:
131; CHECK-NEXT:    br i1 [[COND3]], label %[[BB4]], label %[[BB3]]
132; CHECK:       [[COMMON_RET:.*]]:
133; CHECK-NEXT:    ret void
134; CHECK:       [[BB3]]:
135; CHECK-NEXT:    call void @sideeffect1()
136; CHECK-NEXT:    br label %[[COMMON_RET]]
137; CHECK:       [[BB4]]:
138; CHECK-NEXT:    call void @sideeffect2()
139; CHECK-NEXT:    br label %[[COMMON_RET]]
140;
141entry:
142  br i1 %cond1, label %bb1, label %bb2
143
144bb1:
145  br i1 %cond2, label %bb3, label %bb4
146
147bb2:
148  br i1 %cond3, label %bb4, label %bb3
149
150bb3:
151  call void @sideeffect1()
152  ret void
153
154bb4:
155  call void @sideeffect2()
156  ret void
157}
158
159define 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:.*]]
164; CHECK:       [[BB1]]:
165; CHECK-NEXT:    call void @sideeffect1()
166; CHECK-NEXT:    br i1 [[COND2]], label %[[BB3:.*]], label %[[BB4:.*]]
167; CHECK:       [[BB2]]:
168; CHECK-NEXT:    br i1 [[COND2]], label %[[BB4]], label %[[BB3]]
169; CHECK:       [[COMMON_RET:.*]]:
170; CHECK-NEXT:    ret void
171; CHECK:       [[BB3]]:
172; CHECK-NEXT:    call void @sideeffect1()
173; CHECK-NEXT:    br label %[[COMMON_RET]]
174; CHECK:       [[BB4]]:
175; CHECK-NEXT:    call void @sideeffect2()
176; CHECK-NEXT:    br label %[[COMMON_RET]]
177;
178entry:
179  br i1 %cond1, label %bb1, label %bb2
180
181bb1:
182  call void @sideeffect1()
183  br i1 %cond2, label %bb3, label %bb4
184
185bb2:
186  br i1 %cond2, label %bb4, label %bb3
187
188bb3:
189  call void @sideeffect1()
190  ret void
191
192bb4:
193  call void @sideeffect2()
194  ret void
195}
196
197define 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:.*]]
202; CHECK:       [[BB1]]:
203; CHECK-NEXT:    br i1 [[COND2]], label %[[COMMON_RET:.*]], label %[[BB4:.*]]
204; CHECK:       [[BB2]]:
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]]
209; CHECK:       [[BB4]]:
210; CHECK-NEXT:    call void @sideeffect2()
211; CHECK-NEXT:    br label %[[COMMON_RET]]
212;
213entry:
214  br i1 %cond1, label %bb1, label %bb2
215
216bb1:
217  br i1 %cond2, label %bb3, label %bb4
218
219bb2:
220  br i1 %cond2, label %bb4, label %bb3
221
222bb3:
223  %ret = phi i32 [ 0, %bb1 ], [ %x, %bb2 ]
224  ret i32 %ret
225
226bb4:
227  call void @sideeffect2()
228  ret i32 0
229}
230
231define 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
240; CHECK:       [[BB3]]:
241; CHECK-NEXT:    call void @sideeffect1()
242; CHECK-NEXT:    br label %[[COMMON_RET]]
243; CHECK:       [[BB4]]:
244; CHECK-NEXT:    call void @sideeffect2()
245; CHECK-NEXT:    br label %[[COMMON_RET]]
246;
247entry:
248  br i1 %cond1, label %bb1, label %bb2
249
250bb1:
251  br i1 %cond2, label %bb3, label %bb4
252
253bb2:
254  br i1 %cond2, label %bb1, label %bb3
255
256bb3:
257  call void @sideeffect1()
258  ret void
259
260bb4:
261  call void @sideeffect2()
262  ret void
263}
264
265define 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:.*]]
270; CHECK:       [[BB0]]:
271; CHECK-NEXT:    br i1 [[COND1]], label %[[BB1:.*]], label %[[BB2:.*]]
272; CHECK:       [[BB1]]:
273; CHECK-NEXT:    br i1 [[COND2]], label %[[BB3:.*]], label %[[BB4:.*]]
274; CHECK:       [[BB2]]:
275; CHECK-NEXT:    br i1 [[COND2]], label %[[BB0]], label %[[BB3]]
276; CHECK:       [[COMMON_RET:.*]]:
277; CHECK-NEXT:    ret void
278; CHECK:       [[BB3]]:
279; CHECK-NEXT:    call void @sideeffect1()
280; CHECK-NEXT:    br label %[[COMMON_RET]]
281; CHECK:       [[BB4]]:
282; CHECK-NEXT:    call void @sideeffect2()
283; CHECK-NEXT:    br label %[[COMMON_RET]]
284;
285entry:
286  br label %bb0
287
288bb0:
289  br i1 %cond1, label %bb1, label %bb2
290
291bb1:
292  br i1 %cond2, label %bb3, label %bb4
293
294bb2:
295  br i1 %cond2, label %bb0, label %bb3
296
297bb3:
298  call void @sideeffect1()
299  ret void
300
301bb4:
302  call void @sideeffect2()
303  ret void
304}
305
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
309define 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
317; CHECK:       [[BB3]]:
318; CHECK-NEXT:    call void @sideeffect1()
319; CHECK-NEXT:    br label %[[COMMON_RET]]
320; CHECK:       [[BB4]]:
321; CHECK-NEXT:    call void @sideeffect2()
322; CHECK-NEXT:    br label %[[COMMON_RET]]
323;
324entry:
325  br i1 %cond1, label %bb1, label %bb2, !prof !0 ; 1:2
326
327bb1:
328  br i1 %cond2, label %bb3, label %bb4, !prof !1 ; 3:4
329
330bb2:
331  br i1 %cond2, label %bb4, label %bb3, !prof !2 ; 5:6
332
333bb3:
334  call void @sideeffect1()
335  ret void
336
337bb4:
338  call void @sideeffect2()
339  ret void
340}
341
342!0 = !{!"branch_weights", i32 1, i32 2}
343!1 = !{!"branch_weights", i32 3, i32 4}
344!2 = !{!"branch_weights", i32 5, i32 6}
345
346
347declare void @sideeffect1()
348declare void @sideeffect2()
349;.
350; CHECK: [[PROF0]] = !{!"branch_weights", i32 14, i32 15}
351;.
352