xref: /llvm-project/llvm/test/Transforms/SimplifyCFG/multiple-phis.ll (revision 07b9d231ff9baa6473b0dd588a3ce5330d3e4871)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2
3; RUN: opt -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -keep-loops=false -S < %s | FileCheck %s
4; RUN: opt -passes='simplifycfg<no-keep-loops>' -S < %s | FileCheck %s
5
6; It's not worthwhile to if-convert one of the phi nodes and leave
7; the other behind, because that still requires a branch. If
8; SimplifyCFG if-converts one of the phis, it should do both.
9
10define i32 @upper_bound(ptr %r, i32 %high, i32 %k) nounwind {
11; CHECK-LABEL: define i32 @upper_bound
12; CHECK-SAME: (ptr [[R:%.*]], i32 [[HIGH:%.*]], i32 [[K:%.*]]) #[[ATTR0:[0-9]+]] {
13; CHECK-NEXT:  entry:
14; CHECK-NEXT:    br label [[WHILE_COND:%.*]]
15; CHECK:       while.cond:
16; CHECK-NEXT:    [[HIGH_ADDR_0:%.*]] = phi i32 [ [[HIGH]], [[ENTRY:%.*]] ], [ [[SPEC_SELECT:%.*]], [[WHILE_BODY:%.*]] ]
17; CHECK-NEXT:    [[LOW_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[SPEC_SELECT1:%.*]], [[WHILE_BODY]] ]
18; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[LOW_0]], [[HIGH_ADDR_0]]
19; CHECK-NEXT:    br i1 [[CMP]], label [[WHILE_BODY]], label [[WHILE_END:%.*]]
20; CHECK:       while.body:
21; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[LOW_0]], [[HIGH_ADDR_0]]
22; CHECK-NEXT:    [[DIV:%.*]] = udiv i32 [[ADD]], 2
23; CHECK-NEXT:    [[IDXPROM:%.*]] = zext i32 [[DIV]] to i64
24; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[R]], i64 [[IDXPROM]]
25; CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
26; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[K]], [[TMP0]]
27; CHECK-NEXT:    [[ADD2:%.*]] = add i32 [[DIV]], 1
28; CHECK-NEXT:    [[SPEC_SELECT]] = select i1 [[CMP1]], i32 [[DIV]], i32 [[HIGH_ADDR_0]]
29; CHECK-NEXT:    [[SPEC_SELECT1]] = select i1 [[CMP1]], i32 [[LOW_0]], i32 [[ADD2]]
30; CHECK-NEXT:    br label [[WHILE_COND]]
31; CHECK:       while.end:
32; CHECK-NEXT:    ret i32 [[LOW_0]]
33;
34entry:
35  br label %while.cond
36
37while.cond:                                       ; preds = %if.then, %if.else, %entry
38  %high.addr.0 = phi i32 [ %high, %entry ], [ %div, %if.then ], [ %high.addr.0, %if.else ]
39  %low.0 = phi i32 [ 0, %entry ], [ %low.0, %if.then ], [ %add2, %if.else ]
40  %cmp = icmp ult i32 %low.0, %high.addr.0
41  br i1 %cmp, label %while.body, label %while.end
42
43while.body:                                       ; preds = %while.cond
44  %add = add i32 %low.0, %high.addr.0
45  %div = udiv i32 %add, 2
46  %idxprom = zext i32 %div to i64
47  %arrayidx = getelementptr inbounds i32, ptr %r, i64 %idxprom
48  %0 = load i32, ptr %arrayidx
49  %cmp1 = icmp ult i32 %k, %0
50  br i1 %cmp1, label %if.then, label %if.else
51
52if.then:                                          ; preds = %while.body
53  br label %while.cond
54
55if.else:                                          ; preds = %while.body
56  %add2 = add i32 %div, 1
57  br label %while.cond
58
59while.end:                                        ; preds = %while.cond
60  ret i32 %low.0
61}
62
63define i32 @merge0(i1 %c1, i1 %c2, i1 %c3) {
64; CHECK-LABEL: define i32 @merge0
65; CHECK-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]], i1 [[C3:%.*]]) {
66; CHECK-NEXT:  j2:
67; CHECK-NEXT:    [[DOT:%.*]] = select i1 [[C2]], i32 0, i32 1
68; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[C3]], i32 2, i32 3
69; CHECK-NEXT:    [[PHI2:%.*]] = select i1 [[C1]], i32 [[DOT]], i32 [[SPEC_SELECT]]
70; CHECK-NEXT:    ret i32 [[PHI2]]
71;
72  br i1 %c1, label %if1, label %else1
73
74if1:
75  br i1 %c2, label %if2, label %else2
76
77if2:
78  br label %j1 else2:
79  br label %j1
80
81else1:
82  br i1 %c3, label %j1, label %j2
83
84j1:
85  %phi1 = phi i32 [ 0, %if2 ], [ 1, %else2 ], [ 2, %else1 ]
86  br label %j2
87
88j2:
89  %phi2 = phi i32 [ %phi1, %j1 ], [ 3, %else1 ]
90  ret i32 %phi2
91}
92
93define i8 @merge1(i8 noundef %arg, i1 %c1, i1 %c2) {
94; CHECK-LABEL: define i8 @merge1
95; CHECK-SAME: (i8 noundef [[ARG:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]]) {
96; CHECK-NEXT:  entry:
97; CHECK-NEXT:    switch i8 [[ARG]], label [[UNREACHABLE:%.*]] [
98; CHECK-NEXT:      i8 -123, label [[CASE0:%.*]]
99; CHECK-NEXT:      i8 66, label [[SUCC:%.*]]
100; CHECK-NEXT:      i8 123, label [[CASE2:%.*]]
101; CHECK-NEXT:    ]
102; CHECK:       unreachable:
103; CHECK-NEXT:    unreachable
104; CHECK:       case0:
105; CHECK-NEXT:    [[C1_NOT:%.*]] = xor i1 [[C1]], true
106; CHECK-NEXT:    [[C2_NOT:%.*]] = xor i1 [[C2]], true
107; CHECK-NEXT:    [[BRMERGE:%.*]] = select i1 [[C1_NOT]], i1 true, i1 [[C2_NOT]]
108; CHECK-NEXT:    [[DOTMUX:%.*]] = select i1 [[C1_NOT]], i8 0, i8 3
109; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[BRMERGE]], i8 [[DOTMUX]], i8 4
110; CHECK-NEXT:    br label [[SUCC]]
111; CHECK:       case2:
112; CHECK-NEXT:    br label [[SUCC]]
113; CHECK:       Succ:
114; CHECK-NEXT:    [[PHI2:%.*]] = phi i8 [ 2, [[CASE2]] ], [ 1, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[CASE0]] ]
115; CHECK-NEXT:    ret i8 [[PHI2]]
116;
117entry:
118  switch i8 %arg, label %unreachable [
119  i8 -123, label %case0
120  i8 66, label %case1
121  i8 123, label %case2
122  ]
123
124unreachable:
125  unreachable
126
127case0:
128  br i1 %c1, label %CommonPred, label %BB
129
130case1:
131  br label %BB
132
133case2:
134  br label %BB
135
136CommonPred:
137  br i1 %c2, label %Succ, label %BB
138
139BB:
140  %phi1 = phi i8 [ 0, %case0 ], [1, %case1],[2, %case2],[3,%CommonPred]
141  br label %Succ
142
143Succ:
144  %phi2 = phi i8 [ %phi1, %BB ], [ 4, %CommonPred ]
145  ret i8 %phi2
146}
147
148define i8 @merge1_unfoldable_one_block(i8 noundef %arg, i1 %c1, i1 %c2) {
149; CHECK-LABEL: define i8 @merge1_unfoldable_one_block
150; CHECK-SAME: (i8 noundef [[ARG:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]]) {
151; CHECK-NEXT:  entry:
152; CHECK-NEXT:    switch i8 [[ARG]], label [[UNREACHABLE:%.*]] [
153; CHECK-NEXT:      i8 -123, label [[CASE0:%.*]]
154; CHECK-NEXT:      i8 66, label [[SUCC:%.*]]
155; CHECK-NEXT:      i8 123, label [[CASE2:%.*]]
156; CHECK-NEXT:    ]
157; CHECK:       unreachable:
158; CHECK-NEXT:    unreachable
159; CHECK:       case0:
160; CHECK-NEXT:    call void @dummy()
161; CHECK-NEXT:    [[C1_NOT:%.*]] = xor i1 [[C1]], true
162; CHECK-NEXT:    [[C2_NOT:%.*]] = xor i1 [[C2]], true
163; CHECK-NEXT:    [[BRMERGE:%.*]] = select i1 [[C1_NOT]], i1 true, i1 [[C2_NOT]]
164; CHECK-NEXT:    [[DOTMUX:%.*]] = select i1 [[C1_NOT]], i8 0, i8 3
165; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[BRMERGE]], i8 [[DOTMUX]], i8 4
166; CHECK-NEXT:    br label [[SUCC]]
167; CHECK:       case2:
168; CHECK-NEXT:    br label [[SUCC]]
169; CHECK:       Succ:
170; CHECK-NEXT:    [[PHI2:%.*]] = phi i8 [ 2, [[CASE2]] ], [ 1, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[CASE0]] ]
171; CHECK-NEXT:    ret i8 [[PHI2]]
172;
173entry:
174  switch i8 %arg, label %unreachable [
175  i8 -123, label %case0
176  i8 66, label %case1
177  i8 123, label %case2
178  ]
179
180unreachable:
181  unreachable
182
183case0:
184  call void @dummy()
185  br i1 %c1, label %CommonPred, label %BB
186
187case1:
188  br label %BB
189
190case2:
191  br label %BB
192
193CommonPred:
194  br i1 %c2, label %Succ, label %BB
195
196BB:
197  %phi1 = phi i8 [ 0, %case0 ], [1, %case1],[2, %case2],[3,%CommonPred]
198  br label %Succ
199
200Succ:
201  %phi2 = phi i8 [ %phi1, %BB ], [ 4, %CommonPred ]
202  ret i8 %phi2
203}
204
205define i8 @merge1_unfoldable_two_block(i8 noundef %arg, i1 %c1, i1 %c2) {
206; CHECK-LABEL: define i8 @merge1_unfoldable_two_block
207; CHECK-SAME: (i8 noundef [[ARG:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]]) {
208; CHECK-NEXT:  entry:
209; CHECK-NEXT:    switch i8 [[ARG]], label [[UNREACHABLE:%.*]] [
210; CHECK-NEXT:      i8 -123, label [[CASE0:%.*]]
211; CHECK-NEXT:      i8 66, label [[CASE1:%.*]]
212; CHECK-NEXT:      i8 123, label [[SUCC:%.*]]
213; CHECK-NEXT:    ]
214; CHECK:       unreachable:
215; CHECK-NEXT:    unreachable
216; CHECK:       case0:
217; CHECK-NEXT:    call void @dummy()
218; CHECK-NEXT:    [[C1_NOT:%.*]] = xor i1 [[C1]], true
219; CHECK-NEXT:    [[C2_NOT:%.*]] = xor i1 [[C2]], true
220; CHECK-NEXT:    [[BRMERGE:%.*]] = select i1 [[C1_NOT]], i1 true, i1 [[C2_NOT]]
221; CHECK-NEXT:    [[DOTMUX:%.*]] = select i1 [[C1_NOT]], i8 0, i8 3
222; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[BRMERGE]], i8 [[DOTMUX]], i8 4
223; CHECK-NEXT:    br label [[SUCC]]
224; CHECK:       case1:
225; CHECK-NEXT:    call void @dummy()
226; CHECK-NEXT:    br label [[SUCC]]
227; CHECK:       Succ:
228; CHECK-NEXT:    [[PHI2:%.*]] = phi i8 [ 1, [[CASE1]] ], [ 2, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[CASE0]] ]
229; CHECK-NEXT:    ret i8 [[PHI2]]
230;
231entry:
232  switch i8 %arg, label %unreachable [
233  i8 -123, label %case0
234  i8 66, label %case1
235  i8 123, label %case2
236  ]
237
238unreachable:
239  unreachable
240
241case0:
242call void @dummy()
243  br i1 %c1, label %CommonPred, label %BB
244
245case1:
246call void @dummy()
247  br label %BB
248
249case2:
250  br label %BB
251
252CommonPred:
253  br i1 %c2, label %Succ, label %BB
254
255BB:
256  %phi1 = phi i8 [ 0, %case0 ], [1, %case1],[2, %case2],[3,%CommonPred]
257  br label %Succ
258
259Succ:
260  %phi2 = phi i8 [ %phi1, %BB ], [ 4, %CommonPred ]
261  ret i8 %phi2
262}
263
264define i8 @merge1_unfoldable_all_block(i8 noundef %arg, i1 %c1, i1 %c2) {
265; CHECK-LABEL: define i8 @merge1_unfoldable_all_block
266; CHECK-SAME: (i8 noundef [[ARG:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]]) {
267; CHECK-NEXT:  entry:
268; CHECK-NEXT:    switch i8 [[ARG]], label [[UNREACHABLE:%.*]] [
269; CHECK-NEXT:      i8 -123, label [[CASE0:%.*]]
270; CHECK-NEXT:      i8 66, label [[CASE1:%.*]]
271; CHECK-NEXT:      i8 123, label [[CASE2:%.*]]
272; CHECK-NEXT:    ]
273; CHECK:       unreachable:
274; CHECK-NEXT:    unreachable
275; CHECK:       case0:
276; CHECK-NEXT:    call void @dummy()
277; CHECK-NEXT:    br i1 [[C1]], label [[COMMONPRED:%.*]], label [[SUCC:%.*]]
278; CHECK:       case1:
279; CHECK-NEXT:    call void @dummy()
280; CHECK-NEXT:    br label [[SUCC]]
281; CHECK:       case2:
282; CHECK-NEXT:    call void @dummy()
283; CHECK-NEXT:    br label [[SUCC]]
284; CHECK:       CommonPred:
285; CHECK-NEXT:    call void @dummy()
286; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[C2]], i8 4, i8 3
287; CHECK-NEXT:    br label [[SUCC]]
288; CHECK:       Succ:
289; CHECK-NEXT:    [[PHI2:%.*]] = phi i8 [ 0, [[CASE0]] ], [ 1, [[CASE1]] ], [ 2, [[CASE2]] ], [ [[SPEC_SELECT]], [[COMMONPRED]] ]
290; CHECK-NEXT:    ret i8 [[PHI2]]
291;
292entry:
293  switch i8 %arg, label %unreachable [
294  i8 -123, label %case0
295  i8 66, label %case1
296  i8 123, label %case2
297  ]
298
299unreachable:
300  unreachable
301
302case0:
303call void @dummy()
304  br i1 %c1, label %CommonPred, label %BB
305
306case1:
307call void @dummy()
308  br label %BB
309
310case2:
311call void @dummy()
312  br label %BB
313
314CommonPred:
315call void @dummy()
316  br i1 %c2, label %Succ, label %BB
317
318BB:
319  %phi1 = phi i8 [ 0, %case0 ], [1, %case1],[2, %case2],[3,%CommonPred]
320  br label %Succ
321
322Succ:
323  %phi2 = phi i8 [ %phi1, %BB ], [ 4, %CommonPred ]
324  ret i8 %phi2
325}
326
327declare void @dummy()
328
329