xref: /llvm-project/llvm/test/Transforms/InstCombine/branch.ll (revision 380fa875ab050293be6c8723d770700100b10b8f)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=instcombine -S < %s | FileCheck %s
3
4declare void @use(i1)
5
6; Check that we fold the condition of branches of the
7; form: br <condition> dest1, dest2, where dest1 == dest2.
8define i32 @test(i32 %x) {
9; CHECK-LABEL: @test(
10; CHECK-NEXT:  entry:
11; CHECK-NEXT:    br i1 false, label [[MERGE:%.*]], label [[MERGE]]
12; CHECK:       merge:
13; CHECK-NEXT:    ret i32 [[X:%.*]]
14;
15entry:
16  %cmp = icmp ult i32 %x, 7
17  br i1 %cmp, label %merge, label %merge
18merge:
19  ret i32 %x
20}
21
22@global = global i8 0
23
24define i32 @pat(i32 %x) {
25; CHECK-LABEL: @pat(
26; CHECK-NEXT:    br i1 false, label [[PATATINO:%.*]], label [[PATATINO]]
27; CHECK:       patatino:
28; CHECK-NEXT:    ret i32 [[X:%.*]]
29;
30  %y = icmp eq i32 27, ptrtoint(ptr @global to i32)
31  br i1 %y, label %patatino, label %patatino
32patatino:
33  ret i32 %x
34}
35
36define i1 @test01(i1 %cond) {
37; CHECK-LABEL: @test01(
38; CHECK-NEXT:  entry:
39; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_TRUE_1:%.*]], label [[IF_FALSE_1:%.*]]
40; CHECK:       if.true.1:
41; CHECK-NEXT:    br label [[MERGE_1:%.*]]
42; CHECK:       if.false.1:
43; CHECK-NEXT:    br label [[MERGE_1]]
44; CHECK:       merge.1:
45; CHECK-NEXT:    br i1 [[COND]], label [[IF_TRUE_2:%.*]], label [[IF_FALSE_2:%.*]]
46; CHECK:       if.true.2:
47; CHECK-NEXT:    br label [[MERGE_2:%.*]]
48; CHECK:       if.false.2:
49; CHECK-NEXT:    br label [[MERGE_2]]
50; CHECK:       merge.2:
51; CHECK-NEXT:    ret i1 [[COND]]
52;
53entry:
54  br i1 %cond, label %if.true.1, label %if.false.1
55
56if.true.1:
57  br label %merge.1
58
59if.false.1:
60  br label  %merge.1
61
62merge.1:
63  %merge.cond.1 = phi i1 [true, %if.true.1], [false, %if.false.1]
64  br i1 %merge.cond.1, label %if.true.2, label %if.false.2
65
66if.true.2:
67  br label %merge.2
68
69if.false.2:
70  br label  %merge.2
71
72merge.2:
73  %merge.cond.2 = phi i1 [true, %if.true.2], [false, %if.false.2]
74  ret i1 %merge.cond.2
75}
76
77define i1 @test02(i1 %cond) {
78; CHECK-LABEL: @test02(
79; CHECK-NEXT:  entry:
80; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_TRUE_1:%.*]], label [[IF_FALSE_1:%.*]]
81; CHECK:       if.true.1:
82; CHECK-NEXT:    br label [[MERGE_1:%.*]]
83; CHECK:       if.false.1:
84; CHECK-NEXT:    br label [[MERGE_1]]
85; CHECK:       merge.1:
86; CHECK-NEXT:    br i1 [[COND]], label [[IF_FALSE_2:%.*]], label [[IF_TRUE_2:%.*]]
87; CHECK:       if.true.2:
88; CHECK-NEXT:    br label [[MERGE_2:%.*]]
89; CHECK:       if.false.2:
90; CHECK-NEXT:    br label [[MERGE_2]]
91; CHECK:       merge.2:
92; CHECK-NEXT:    ret i1 [[COND]]
93;
94entry:
95  br i1 %cond, label %if.true.1, label %if.false.1
96
97if.true.1:
98  br label %merge.1
99
100if.false.1:
101  br label  %merge.1
102
103merge.1:
104  %merge.cond.1 = phi i1 [false, %if.true.1], [true, %if.false.1]
105  br i1 %merge.cond.1, label %if.true.2, label %if.false.2
106
107if.true.2:
108  br label %merge.2
109
110if.false.2:
111  br label  %merge.2
112
113merge.2:
114  %merge.cond.2 = phi i1 [false, %if.true.2], [true, %if.false.2]
115  ret i1 %merge.cond.2
116}
117
118; if (x && !y) ret 42; ret 3 --> if (!x || y) ret 3; ret 42
119
120define i32 @logical_and_not(i1 %x, i1 %y) {
121; CHECK-LABEL: @logical_and_not(
122; CHECK-NEXT:  entry:
123; CHECK-NEXT:    [[NOT_X:%.*]] = xor i1 [[X:%.*]], true
124; CHECK-NEXT:    [[TMP0:%.*]] = select i1 [[NOT_X]], i1 true, i1 [[Y:%.*]]
125; CHECK-NEXT:    br i1 [[TMP0]], label [[F:%.*]], label [[T:%.*]]
126; CHECK:       t:
127; CHECK-NEXT:    ret i32 42
128; CHECK:       f:
129; CHECK-NEXT:    ret i32 3
130;
131entry:
132  %noty = xor i1 %y, true
133  %and = select i1 %x, i1 %noty, i1 false
134  br i1 %and, label %t, label %f
135
136t:
137  ret i32 42
138
139f:
140  ret i32 3
141}
142
143; if (x && y || !x) ret 3; ret 42 --> if (!x || y) ret 3; ret 42
144
145define i32 @logical_and_or(i1 %x, i1 %y) {
146; CHECK-LABEL: @logical_and_or(
147; CHECK-NEXT:  entry:
148; CHECK-NEXT:    [[NOT_X:%.*]] = xor i1 [[X:%.*]], true
149; CHECK-NEXT:    [[AND:%.*]] = select i1 [[NOT_X]], i1 true, i1 [[Y:%.*]]
150; CHECK-NEXT:    br i1 [[AND]], label [[F:%.*]], label [[T:%.*]]
151; CHECK:       t:
152; CHECK-NEXT:    ret i32 42
153; CHECK:       f:
154; CHECK-NEXT:    ret i32 3
155;
156entry:
157  %and = select i1 %x, i1 %y, i1 true
158  br i1 %and, label %f, label %t
159
160t:
161  ret i32 42
162
163f:
164  ret i32 3
165}
166
167; if (!x || y) ret 3; ret 42
168
169define i32 @logical_or_not(i1 %x, i1 %y) {
170; CHECK-LABEL: @logical_or_not(
171; CHECK-NEXT:  entry:
172; CHECK-NEXT:    [[NOTX:%.*]] = xor i1 [[X:%.*]], true
173; CHECK-NEXT:    [[AND:%.*]] = select i1 [[NOTX]], i1 true, i1 [[Y:%.*]]
174; CHECK-NEXT:    br i1 [[AND]], label [[F:%.*]], label [[T:%.*]]
175; CHECK:       t:
176; CHECK-NEXT:    ret i32 42
177; CHECK:       f:
178; CHECK-NEXT:    ret i32 3
179;
180entry:
181  %notx = xor i1 %x, true
182  %and = select i1 %notx, i1 true, i1 %y
183  br i1 %and, label %f, label %t
184
185t:
186  ret i32 42
187
188f:
189  ret i32 3
190}
191
192; negative test
193
194define i32 @logical_and_not_use1(i1 %x, i1 %y) {
195; CHECK-LABEL: @logical_and_not_use1(
196; CHECK-NEXT:  entry:
197; CHECK-NEXT:    [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
198; CHECK-NEXT:    call void @use(i1 [[NOTY]])
199; CHECK-NEXT:    [[AND:%.*]] = select i1 [[X:%.*]], i1 [[NOTY]], i1 false
200; CHECK-NEXT:    br i1 [[AND]], label [[T:%.*]], label [[F:%.*]]
201; CHECK:       t:
202; CHECK-NEXT:    ret i32 42
203; CHECK:       f:
204; CHECK-NEXT:    ret i32 3
205;
206entry:
207  %noty = xor i1 %y, true
208  call void @use(i1 %noty)
209  %and = select i1 %x, i1 %noty, i1 false
210  br i1 %and, label %t, label %f
211
212t:
213  ret i32 42
214
215f:
216  ret i32 3
217}
218
219; negative test
220
221define i32 @logical_and_not_use2(i1 %x, i1 %y) {
222; CHECK-LABEL: @logical_and_not_use2(
223; CHECK-NEXT:  entry:
224; CHECK-NEXT:    [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
225; CHECK-NEXT:    [[AND:%.*]] = select i1 [[X:%.*]], i1 [[NOTY]], i1 false
226; CHECK-NEXT:    call void @use(i1 [[AND]])
227; CHECK-NEXT:    br i1 [[AND]], label [[T:%.*]], label [[F:%.*]]
228; CHECK:       t:
229; CHECK-NEXT:    ret i32 42
230; CHECK:       f:
231; CHECK-NEXT:    ret i32 3
232;
233entry:
234  %noty = xor i1 %y, true
235  %and = select i1 %x, i1 %noty, i1 false
236  call void @use(i1 %and)
237  br i1 %and, label %t, label %f
238
239t:
240  ret i32 42
241
242f:
243  ret i32 3
244}
245
246define i32 @dom_true(i1 %cmp) {
247; CHECK-LABEL: @dom_true(
248; CHECK-NEXT:    br i1 [[CMP:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
249; CHECK:       if.then:
250; CHECK-NEXT:    ret i32 1
251; CHECK:       if.else:
252; CHECK-NEXT:    ret i32 0
253;
254  br i1 %cmp, label %if.then, label %if.else
255
256if.then:
257  %zext = zext i1 %cmp to i32
258  ret i32 %zext
259
260if.else:
261  ret i32 0
262}
263
264define i32 @dom_false(i1 %cmp) {
265; CHECK-LABEL: @dom_false(
266; CHECK-NEXT:    br i1 [[CMP:%.*]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
267; CHECK:       if.then:
268; CHECK-NEXT:    ret i32 0
269; CHECK:       if.else:
270; CHECK-NEXT:    ret i32 0
271;
272  br i1 %cmp, label %if.else, label %if.then
273
274if.then:
275  %zext = zext i1 %cmp to i32
276  ret i32 %zext
277
278if.else:
279  ret i32 0
280}
281
282define i32 @dom_true_phi(i1 %cmp) {
283; CHECK-LABEL: @dom_true_phi(
284; CHECK-NEXT:    br i1 [[CMP:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
285; CHECK:       if.then:
286; CHECK-NEXT:    br label [[IF_END:%.*]]
287; CHECK:       if.else:
288; CHECK-NEXT:    br label [[IF_END]]
289; CHECK:       if.end:
290; CHECK-NEXT:    [[ZEXT:%.*]] = zext i1 [[CMP]] to i32
291; CHECK-NEXT:    ret i32 [[ZEXT]]
292;
293  br i1 %cmp, label %if.then, label %if.else
294
295if.then:
296  br label %if.end
297
298if.else:
299  br label %if.end
300
301if.end:
302  %phi = phi i1 [ true, %if.then ], [ %cmp, %if.else ]
303  %zext = zext i1 %phi to i32
304  ret i32 %zext
305}
306
307; Negative tests
308
309define i32 @same_dest(i1 %cmp) {
310; CHECK-LABEL: @same_dest(
311; CHECK-NEXT:    br i1 false, label [[IF_THEN:%.*]], label [[IF_THEN]]
312; CHECK:       if.then:
313; CHECK-NEXT:    [[ZEXT:%.*]] = zext i1 [[CMP:%.*]] to i32
314; CHECK-NEXT:    ret i32 [[ZEXT]]
315;
316  br i1 %cmp, label %if.then, label %if.then
317
318if.then:
319  %zext = zext i1 %cmp to i32
320  ret i32 %zext
321}
322
323define i32 @not_dom(i1 %cmp) {
324; CHECK-LABEL: @not_dom(
325; CHECK-NEXT:    br i1 [[CMP:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
326; CHECK:       if.then:
327; CHECK-NEXT:    br label [[IF_ELSE]]
328; CHECK:       if.else:
329; CHECK-NEXT:    [[ZEXT:%.*]] = zext i1 [[CMP]] to i32
330; CHECK-NEXT:    ret i32 [[ZEXT]]
331;
332  br i1 %cmp, label %if.then, label %if.else
333
334if.then:
335  br label %if.else
336
337if.else:
338  %zext = zext i1 %cmp to i32
339  ret i32 %zext
340}
341