1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -mtriple=thumbv8m.main %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB
3 ; RUN: opt -mtriple=thumbv8a %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB
4 ; RUN: opt -mtriple=armv8a %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s --check-prefix=CHECK --check-prefix=ARM
6 define i32 @foo(i32 %a, i32 %b, i32 %c, i32 %d, ptr %input) {
9 ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[D:%.*]], 3
10 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[C:%.*]], [[A:%.*]]
11 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[ADD]], [[B:%.*]]
12 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 [[CMP1]], i1 false
13 ; CHECK-NEXT: br i1 [[OR_COND]], label [[COND_FALSE:%.*]], label [[COND_END:%.*]]
15 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[INPUT:%.*]], align 4
16 ; CHECK-NEXT: br label [[COND_END]]
18 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[TMP0]], [[COND_FALSE]] ], [ 0, [[ENTRY:%.*]] ]
19 ; CHECK-NEXT: ret i32 [[COND]]
22 %cmp = icmp sgt i32 %d, 3
23 br i1 %cmp, label %cond.end, label %lor.lhs.false
26 %add = add nsw i32 %c, %a
27 %cmp1 = icmp slt i32 %add, %b
28 br i1 %cmp1, label %cond.false, label %cond.end
31 %0 = load i32, ptr %input, align 4
35 %cond = phi i32 [ %0, %cond.false ], [ 0, %lor.lhs.false ], [ 0, %entry ]
39 define i32 @foo_minsize(i32 %a, i32 %b, i32 %c, i32 %d, ptr %input) #0 {
40 ; CHECK-LABEL: @foo_minsize(
42 ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[D:%.*]], 3
43 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[C:%.*]], [[A:%.*]]
44 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[ADD]], [[B:%.*]]
45 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 [[CMP1]], i1 false
46 ; CHECK-NEXT: br i1 [[OR_COND]], label [[COND_FALSE:%.*]], label [[COND_END:%.*]]
48 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[INPUT:%.*]], align 4
49 ; CHECK-NEXT: br label [[COND_END]]
51 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[TMP0]], [[COND_FALSE]] ], [ 0, [[ENTRY:%.*]] ]
52 ; CHECK-NEXT: ret i32 [[COND]]
55 %cmp = icmp sgt i32 %d, 3
56 br i1 %cmp, label %cond.end, label %lor.lhs.false
59 %add = add nsw i32 %c, %a
60 %cmp1 = icmp slt i32 %add, %b
61 br i1 %cmp1, label %cond.false, label %cond.end
64 %0 = load i32, ptr %input, align 4
68 %cond = phi i32 [ %0, %cond.false ], [ 0, %lor.lhs.false ], [ 0, %entry ]
72 define i32 @foo_minsize_i64(i64 %a, i64 %b, i64 %c, i64 %d, ptr %input) #0 {
73 ; CHECK-LABEL: @foo_minsize_i64(
75 ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i64 [[D:%.*]], 3
76 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[C:%.*]], [[A:%.*]]
77 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 [[ADD]], [[B:%.*]]
78 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 [[CMP1]], i1 false
79 ; CHECK-NEXT: br i1 [[OR_COND]], label [[COND_FALSE:%.*]], label [[COND_END:%.*]]
81 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[INPUT:%.*]], align 4
82 ; CHECK-NEXT: br label [[COND_END]]
84 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[TMP0]], [[COND_FALSE]] ], [ 0, [[ENTRY:%.*]] ]
85 ; CHECK-NEXT: ret i32 [[COND]]
88 %cmp = icmp sgt i64 %d, 3
89 br i1 %cmp, label %cond.end, label %lor.lhs.false
92 %add = add nsw i64 %c, %a
93 %cmp1 = icmp slt i64 %add, %b
94 br i1 %cmp1, label %cond.false, label %cond.end
97 %0 = load i32, ptr %input, align 4
101 %cond = phi i32 [ %0, %cond.false ], [ 0, %lor.lhs.false ], [ 0, %entry ]
105 define i32 @or_predicate(i32 %a, i32 %b, i32 %c, i32 %d, ptr %input) {
106 ; CHECK-LABEL: @or_predicate(
108 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[D:%.*]], 3
109 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[C:%.*]], [[A:%.*]]
110 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[ADD]], [[B:%.*]]
111 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 true, i1 [[CMP1]]
112 ; CHECK-NEXT: br i1 [[OR_COND]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
114 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[INPUT:%.*]], align 4
115 ; CHECK-NEXT: br label [[COND_END]]
117 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[TMP0]], [[COND_FALSE]] ], [ 0, [[ENTRY:%.*]] ]
118 ; CHECK-NEXT: ret i32 [[COND]]
121 %cmp = icmp sgt i32 %d, 3
122 br i1 %cmp, label %cond.end, label %lor.lhs.false
125 %add = add nsw i32 %c, %a
126 %cmp1 = icmp slt i32 %add, %b
127 br i1 %cmp1, label %cond.end, label %cond.false
130 %0 = load i32, ptr %input, align 4
134 %cond = phi i32 [ %0, %cond.false ], [ 0, %lor.lhs.false ], [ 0, %entry ]
138 define i32 @or_invert_predicate(i32 %a, i32 %b, i32 %c, i32 %d, ptr %input) {
139 ; CHECK-LABEL: @or_invert_predicate(
141 ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[D:%.*]], 3
142 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[C:%.*]], [[A:%.*]]
143 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[ADD]], [[B:%.*]]
144 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 true, i1 [[CMP1]]
145 ; CHECK-NEXT: br i1 [[OR_COND]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
147 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[INPUT:%.*]], align 4
148 ; CHECK-NEXT: br label [[COND_END]]
150 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[TMP0]], [[COND_FALSE]] ], [ 0, [[ENTRY:%.*]] ]
151 ; CHECK-NEXT: ret i32 [[COND]]
154 %cmp = icmp sgt i32 %d, 3
155 br i1 %cmp, label %lor.lhs.false, label %cond.end
158 %add = add nsw i32 %c, %a
159 %cmp1 = icmp slt i32 %add, %b
160 br i1 %cmp1, label %cond.end, label %cond.false
163 %0 = load i32, ptr %input, align 4
167 %cond = phi i32 [ %0, %cond.false ], [ 0, %lor.lhs.false ], [ 0, %entry ]
171 define i32 @or_predicate_minsize(i32 %a, i32 %b, i32 %c, i32 %d, ptr %input) #0 {
172 ; THUMB-LABEL: @or_predicate_minsize(
174 ; THUMB-NEXT: [[CMP:%.*]] = icmp sgt i32 [[D:%.*]], 3
175 ; THUMB-NEXT: br i1 [[CMP]], label [[COND_END:%.*]], label [[LOR_LHS_FALSE:%.*]]
176 ; THUMB: lor.lhs.false:
177 ; THUMB-NEXT: [[ADD:%.*]] = add nsw i32 [[C:%.*]], [[A:%.*]]
178 ; THUMB-NEXT: [[CMP1:%.*]] = icmp slt i32 [[ADD]], [[B:%.*]]
179 ; THUMB-NEXT: br i1 [[CMP1]], label [[COND_END]], label [[COND_FALSE:%.*]]
181 ; THUMB-NEXT: [[TMP0:%.*]] = load i32, ptr [[INPUT:%.*]], align 4
182 ; THUMB-NEXT: br label [[COND_END]]
184 ; THUMB-NEXT: [[COND:%.*]] = phi i32 [ [[TMP0]], [[COND_FALSE]] ], [ 0, [[LOR_LHS_FALSE]] ], [ 0, [[ENTRY:%.*]] ]
185 ; THUMB-NEXT: ret i32 [[COND]]
187 ; ARM-LABEL: @or_predicate_minsize(
189 ; ARM-NEXT: [[CMP:%.*]] = icmp sgt i32 [[D:%.*]], 3
190 ; ARM-NEXT: [[ADD:%.*]] = add nsw i32 [[C:%.*]], [[A:%.*]]
191 ; ARM-NEXT: [[CMP1:%.*]] = icmp slt i32 [[ADD]], [[B:%.*]]
192 ; ARM-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 true, i1 [[CMP1]]
193 ; ARM-NEXT: br i1 [[OR_COND]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
195 ; ARM-NEXT: [[TMP0:%.*]] = load i32, ptr [[INPUT:%.*]], align 4
196 ; ARM-NEXT: br label [[COND_END]]
198 ; ARM-NEXT: [[COND:%.*]] = phi i32 [ [[TMP0]], [[COND_FALSE]] ], [ 0, [[ENTRY:%.*]] ]
199 ; ARM-NEXT: ret i32 [[COND]]
202 %cmp = icmp sgt i32 %d, 3
203 br i1 %cmp, label %cond.end, label %lor.lhs.false
206 %add = add nsw i32 %c, %a
207 %cmp1 = icmp slt i32 %add, %b
208 br i1 %cmp1, label %cond.end, label %cond.false
211 %0 = load i32, ptr %input, align 4
215 %cond = phi i32 [ %0, %cond.false ], [ 0, %lor.lhs.false ], [ 0, %entry ]
219 define i32 @or_invert_predicate_minsize(i32 %a, i32 %b, i32 %c, i32 %d, ptr %input) #0 {
220 ; THUMB-LABEL: @or_invert_predicate_minsize(
222 ; THUMB-NEXT: [[CMP:%.*]] = icmp sgt i32 [[D:%.*]], 3
223 ; THUMB-NEXT: br i1 [[CMP]], label [[LOR_LHS_FALSE:%.*]], label [[COND_END:%.*]]
224 ; THUMB: lor.lhs.false:
225 ; THUMB-NEXT: [[ADD:%.*]] = add nsw i32 [[C:%.*]], [[A:%.*]]
226 ; THUMB-NEXT: [[CMP1:%.*]] = icmp slt i32 [[ADD]], [[B:%.*]]
227 ; THUMB-NEXT: br i1 [[CMP1]], label [[COND_END]], label [[COND_FALSE:%.*]]
229 ; THUMB-NEXT: [[TMP0:%.*]] = load i32, ptr [[INPUT:%.*]], align 4
230 ; THUMB-NEXT: br label [[COND_END]]
232 ; THUMB-NEXT: [[COND:%.*]] = phi i32 [ [[TMP0]], [[COND_FALSE]] ], [ 0, [[LOR_LHS_FALSE]] ], [ 0, [[ENTRY:%.*]] ]
233 ; THUMB-NEXT: ret i32 [[COND]]
235 ; ARM-LABEL: @or_invert_predicate_minsize(
237 ; ARM-NEXT: [[CMP:%.*]] = icmp sle i32 [[D:%.*]], 3
238 ; ARM-NEXT: [[ADD:%.*]] = add nsw i32 [[C:%.*]], [[A:%.*]]
239 ; ARM-NEXT: [[CMP1:%.*]] = icmp slt i32 [[ADD]], [[B:%.*]]
240 ; ARM-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 true, i1 [[CMP1]]
241 ; ARM-NEXT: br i1 [[OR_COND]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
243 ; ARM-NEXT: [[TMP0:%.*]] = load i32, ptr [[INPUT:%.*]], align 4
244 ; ARM-NEXT: br label [[COND_END]]
246 ; ARM-NEXT: [[COND:%.*]] = phi i32 [ [[TMP0]], [[COND_FALSE]] ], [ 0, [[ENTRY:%.*]] ]
247 ; ARM-NEXT: ret i32 [[COND]]
250 %cmp = icmp sgt i32 %d, 3
251 br i1 %cmp, label %lor.lhs.false, label %cond.end
254 %add = add nsw i32 %c, %a
255 %cmp1 = icmp slt i32 %add, %b
256 br i1 %cmp1, label %cond.end, label %cond.false
259 %0 = load i32, ptr %input, align 4
263 %cond = phi i32 [ %0, %cond.false ], [ 0, %lor.lhs.false ], [ 0, %entry ]
267 define i32 @or_xor_predicate(i32 %a, i32 %b, i32 %c, i32 %d, ptr %input, i1 %cmp) {
268 ; CHECK-LABEL: @or_xor_predicate(
270 ; CHECK-NEXT: [[CMP_NOT:%.*]] = xor i1 [[CMP:%.*]], true
271 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[C:%.*]], [[A:%.*]]
272 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[ADD]], [[B:%.*]]
273 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP_NOT]], i1 true, i1 [[CMP1]]
274 ; CHECK-NEXT: br i1 [[OR_COND]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
276 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[INPUT:%.*]], align 4
277 ; CHECK-NEXT: br label [[COND_END]]
279 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[TMP0]], [[COND_FALSE]] ], [ 0, [[ENTRY:%.*]] ]
280 ; CHECK-NEXT: ret i32 [[COND]]
283 br i1 %cmp, label %lor.lhs.false, label %cond.end
286 %add = add nsw i32 %c, %a
287 %cmp1 = icmp slt i32 %add, %b
288 br i1 %cmp1, label %cond.end, label %cond.false
291 %0 = load i32, ptr %input, align 4
295 %cond = phi i32 [ %0, %cond.false ], [ 0, %lor.lhs.false ], [ 0, %entry ]
299 define i32 @or_xor_predicate_minsize(i32 %a, i32 %b, i32 %c, i32 %d, ptr %input, i1 %cmp) #0 {
300 ; THUMB-LABEL: @or_xor_predicate_minsize(
302 ; THUMB-NEXT: br i1 [[CMP:%.*]], label [[LOR_LHS_FALSE:%.*]], label [[COND_END:%.*]]
303 ; THUMB: lor.lhs.false:
304 ; THUMB-NEXT: [[ADD:%.*]] = add nsw i32 [[C:%.*]], [[A:%.*]]
305 ; THUMB-NEXT: [[CMP1:%.*]] = icmp slt i32 [[ADD]], [[B:%.*]]
306 ; THUMB-NEXT: br i1 [[CMP1]], label [[COND_END]], label [[COND_FALSE:%.*]]
308 ; THUMB-NEXT: [[TMP0:%.*]] = load i32, ptr [[INPUT:%.*]], align 4
309 ; THUMB-NEXT: br label [[COND_END]]
311 ; THUMB-NEXT: [[COND:%.*]] = phi i32 [ [[TMP0]], [[COND_FALSE]] ], [ 0, [[LOR_LHS_FALSE]] ], [ 0, [[ENTRY:%.*]] ]
312 ; THUMB-NEXT: ret i32 [[COND]]
314 ; ARM-LABEL: @or_xor_predicate_minsize(
316 ; ARM-NEXT: [[CMP_NOT:%.*]] = xor i1 [[CMP:%.*]], true
317 ; ARM-NEXT: [[ADD:%.*]] = add nsw i32 [[C:%.*]], [[A:%.*]]
318 ; ARM-NEXT: [[CMP1:%.*]] = icmp slt i32 [[ADD]], [[B:%.*]]
319 ; ARM-NEXT: [[OR_COND:%.*]] = select i1 [[CMP_NOT]], i1 true, i1 [[CMP1]]
320 ; ARM-NEXT: br i1 [[OR_COND]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
322 ; ARM-NEXT: [[TMP0:%.*]] = load i32, ptr [[INPUT:%.*]], align 4
323 ; ARM-NEXT: br label [[COND_END]]
325 ; ARM-NEXT: [[COND:%.*]] = phi i32 [ [[TMP0]], [[COND_FALSE]] ], [ 0, [[ENTRY:%.*]] ]
326 ; ARM-NEXT: ret i32 [[COND]]
329 br i1 %cmp, label %lor.lhs.false, label %cond.end
332 %add = add nsw i32 %c, %a
333 %cmp1 = icmp slt i32 %add, %b
334 br i1 %cmp1, label %cond.end, label %cond.false
337 %0 = load i32, ptr %input, align 4
341 %cond = phi i32 [ %0, %cond.false ], [ 0, %lor.lhs.false ], [ 0, %entry ]
345 define i32 @and_xor(i32 %a, i32 %b, i32 %c, i32 %d, ptr %input, i1 %cmp) {
346 ; CHECK-LABEL: @and_xor(
348 ; CHECK-NEXT: [[CMP_NOT:%.*]] = xor i1 [[CMP:%.*]], true
349 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[C:%.*]], [[A:%.*]]
350 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[ADD]], [[B:%.*]]
351 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP_NOT]], i1 [[CMP1]], i1 false
352 ; CHECK-NEXT: br i1 [[OR_COND]], label [[COND_FALSE:%.*]], label [[COND_END:%.*]]
354 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[INPUT:%.*]], align 4
355 ; CHECK-NEXT: br label [[COND_END]]
357 ; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[TMP0]], [[COND_FALSE]] ], [ 0, [[ENTRY:%.*]] ]
358 ; CHECK-NEXT: ret i32 [[COND]]
361 br i1 %cmp, label %cond.end, label %lor.lhs.false
364 %add = add nsw i32 %c, %a
365 %cmp1 = icmp slt i32 %add, %b
366 br i1 %cmp1, label %cond.false, label %cond.end
369 %0 = load i32, ptr %input, align 4
373 %cond = phi i32 [ %0, %cond.false ], [ 0, %lor.lhs.false ], [ 0, %entry ]
377 define i32 @and_xor_minsize(i32 %a, i32 %b, i32 %c, i32 %d, ptr %input, i1 %cmp) #0 {
378 ; THUMB-LABEL: @and_xor_minsize(
380 ; THUMB-NEXT: br i1 [[CMP:%.*]], label [[COND_END:%.*]], label [[LOR_LHS_FALSE:%.*]]
381 ; THUMB: lor.lhs.false:
382 ; THUMB-NEXT: [[ADD:%.*]] = add nsw i32 [[C:%.*]], [[A:%.*]]
383 ; THUMB-NEXT: [[CMP1:%.*]] = icmp slt i32 [[ADD]], [[B:%.*]]
384 ; THUMB-NEXT: br i1 [[CMP1]], label [[COND_FALSE:%.*]], label [[COND_END]]
386 ; THUMB-NEXT: [[TMP0:%.*]] = load i32, ptr [[INPUT:%.*]], align 4
387 ; THUMB-NEXT: br label [[COND_END]]
389 ; THUMB-NEXT: [[COND:%.*]] = phi i32 [ [[TMP0]], [[COND_FALSE]] ], [ 0, [[LOR_LHS_FALSE]] ], [ 0, [[ENTRY:%.*]] ]
390 ; THUMB-NEXT: ret i32 [[COND]]
392 ; ARM-LABEL: @and_xor_minsize(
394 ; ARM-NEXT: [[CMP_NOT:%.*]] = xor i1 [[CMP:%.*]], true
395 ; ARM-NEXT: [[ADD:%.*]] = add nsw i32 [[C:%.*]], [[A:%.*]]
396 ; ARM-NEXT: [[CMP1:%.*]] = icmp slt i32 [[ADD]], [[B:%.*]]
397 ; ARM-NEXT: [[OR_COND:%.*]] = select i1 [[CMP_NOT]], i1 [[CMP1]], i1 false
398 ; ARM-NEXT: br i1 [[OR_COND]], label [[COND_FALSE:%.*]], label [[COND_END:%.*]]
400 ; ARM-NEXT: [[TMP0:%.*]] = load i32, ptr [[INPUT:%.*]], align 4
401 ; ARM-NEXT: br label [[COND_END]]
403 ; ARM-NEXT: [[COND:%.*]] = phi i32 [ [[TMP0]], [[COND_FALSE]] ], [ 0, [[ENTRY:%.*]] ]
404 ; ARM-NEXT: ret i32 [[COND]]
407 br i1 %cmp, label %cond.end, label %lor.lhs.false
410 %add = add nsw i32 %c, %a
411 %cmp1 = icmp slt i32 %add, %b
412 br i1 %cmp1, label %cond.false, label %cond.end
415 %0 = load i32, ptr %input, align 4
419 %cond = phi i32 [ %0, %cond.false ], [ 0, %lor.lhs.false ], [ 0, %entry ]
423 attributes #0 = { minsize optsize }