1; RUN: llc < %s -stress-early-ifcvt -aarch64-enable-atomic-cfg-tidy=0 | FileCheck %s
2target triple = "arm64-apple-macosx"
3
4; CHECK: mm2
5define i32 @mm2(i32* nocapture %p, i32 %n) nounwind uwtable readonly ssp {
6entry:
7  br label %do.body
8
9; CHECK: do.body
10; Loop body has no branches before the backedge.
11; CHECK-NOT: LBB
12do.body:
13  %max.0 = phi i32 [ 0, %entry ], [ %max.1, %do.cond ]
14  %min.0 = phi i32 [ 0, %entry ], [ %min.1, %do.cond ]
15  %n.addr.0 = phi i32 [ %n, %entry ], [ %dec, %do.cond ]
16  %p.addr.0 = phi i32* [ %p, %entry ], [ %incdec.ptr, %do.cond ]
17  %incdec.ptr = getelementptr inbounds i32, i32* %p.addr.0, i64 1
18  %0 = load i32, i32* %p.addr.0, align 4
19  %cmp = icmp sgt i32 %0, %max.0
20  br i1 %cmp, label %do.cond, label %if.else
21
22if.else:
23  %cmp1 = icmp slt i32 %0, %min.0
24  %.min.0 = select i1 %cmp1, i32 %0, i32 %min.0
25  br label %do.cond
26
27do.cond:
28  %max.1 = phi i32 [ %0, %do.body ], [ %max.0, %if.else ]
29  %min.1 = phi i32 [ %min.0, %do.body ], [ %.min.0, %if.else ]
30; CHECK: b.ne
31  %dec = add i32 %n.addr.0, -1
32  %tobool = icmp eq i32 %dec, 0
33  br i1 %tobool, label %do.end, label %do.body
34
35do.end:
36  %sub = sub nsw i32 %max.1, %min.1
37  ret i32 %sub
38}
39
40; CHECK-LABEL: fold_inc_true_32:
41; CHECK: {{subs.*wzr,|cmp}} w2, #1
42; CHECK-NEXT: csinc w0, w1, w0, eq
43; CHECK-NEXT: ret
44define i32 @fold_inc_true_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
45entry:
46  %tobool = icmp eq i32 %c, 1
47  %inc = add nsw i32 %x, 1
48  br i1 %tobool, label %eq_bb, label %done
49
50eq_bb:
51  br label %done
52
53done:
54  %cond = phi i32 [ %y, %eq_bb ], [ %inc, %entry ]
55  ret i32 %cond
56}
57
58; CHECK-LABEL: fold_inc_true_64:
59; CHECK: {{subs.*xzr,|cmp}} x2, #1
60; CHECK-NEXT: csinc x0, x1, x0, eq
61; CHECK-NEXT: ret
62define i64 @fold_inc_true_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
63entry:
64  %tobool = icmp eq i64 %c, 1
65  %inc = add nsw i64 %x, 1
66  br i1 %tobool, label %eq_bb, label %done
67
68eq_bb:
69  br label %done
70
71done:
72  %cond = phi i64 [ %y, %eq_bb ], [ %inc, %entry ]
73  ret i64 %cond
74}
75
76; CHECK-LABEL: fold_inc_false_32:
77; CHECK: {{subs.*wzr,|cmp}} w2, #1
78; CHECK-NEXT: csinc w0, w1, w0, ne
79; CHECK-NEXT: ret
80define i32 @fold_inc_false_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
81entry:
82  %tobool = icmp eq i32 %c, 1
83  %inc = add nsw i32 %x, 1
84  br i1 %tobool, label %eq_bb, label %done
85
86eq_bb:
87  br label %done
88
89done:
90  %cond = phi i32 [ %inc, %eq_bb ], [ %y, %entry ]
91  ret i32 %cond
92}
93
94; CHECK-LABEL: fold_inc_false_64:
95; CHECK: {{subs.*xzr,|cmp}} x2, #1
96; CHECK-NEXT: csinc x0, x1, x0, ne
97; CHECK-NEXT: ret
98define i64 @fold_inc_false_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
99entry:
100  %tobool = icmp eq i64 %c, 1
101  %inc = add nsw i64 %x, 1
102  br i1 %tobool, label %eq_bb, label %done
103
104eq_bb:
105  br label %done
106
107done:
108  %cond = phi i64 [ %inc, %eq_bb ], [ %y, %entry ]
109  ret i64 %cond
110}
111
112; CHECK-LABEL: fold_inv_true_32:
113; CHECK: {{subs.*wzr,|cmp}} w2, #1
114; CHECK-NEXT: csinv w0, w1, w0, eq
115; CHECK-NEXT: ret
116define i32 @fold_inv_true_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
117entry:
118  %tobool = icmp eq i32 %c, 1
119  %inv = xor i32 %x, -1
120  br i1 %tobool, label %eq_bb, label %done
121
122eq_bb:
123  br label %done
124
125done:
126  %cond = phi i32 [ %y, %eq_bb ], [ %inv, %entry ]
127  ret i32 %cond
128}
129
130; CHECK-LABEL: fold_inv_true_64:
131; CHECK: {{subs.*xzr,|cmp}} x2, #1
132; CHECK-NEXT: csinv x0, x1, x0, eq
133; CHECK-NEXT: ret
134define i64 @fold_inv_true_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
135entry:
136  %tobool = icmp eq i64 %c, 1
137  %inv = xor i64 %x, -1
138  br i1 %tobool, label %eq_bb, label %done
139
140eq_bb:
141  br label %done
142
143done:
144  %cond = phi i64 [ %y, %eq_bb ], [ %inv, %entry ]
145  ret i64 %cond
146}
147
148; CHECK-LABEL: fold_inv_false_32:
149; CHECK: {{subs.*wzr,|cmp}} w2, #1
150; CHECK-NEXT: csinv w0, w1, w0, ne
151; CHECK-NEXT: ret
152define i32 @fold_inv_false_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
153entry:
154  %tobool = icmp eq i32 %c, 1
155  %inv = xor i32 %x, -1
156  br i1 %tobool, label %eq_bb, label %done
157
158eq_bb:
159  br label %done
160
161done:
162  %cond = phi i32 [ %inv, %eq_bb ], [ %y, %entry ]
163  ret i32 %cond
164}
165
166; CHECK-LABEL: fold_inv_false_64:
167; CHECK: {{subs.*xzr,|cmp}} x2, #1
168; CHECK-NEXT: csinv x0, x1, x0, ne
169; CHECK-NEXT: ret
170define i64 @fold_inv_false_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
171entry:
172  %tobool = icmp eq i64 %c, 1
173  %inv = xor i64 %x, -1
174  br i1 %tobool, label %eq_bb, label %done
175
176eq_bb:
177  br label %done
178
179done:
180  %cond = phi i64 [ %inv, %eq_bb ], [ %y, %entry ]
181  ret i64 %cond
182}
183
184; CHECK-LABEL: fold_neg_true_32:
185; CHECK: {{subs.*wzr,|cmp}} w2, #1
186; CHECK-NEXT: csneg w0, w1, w0, eq
187; CHECK-NEXT: ret
188define i32 @fold_neg_true_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
189entry:
190  %tobool = icmp eq i32 %c, 1
191  %neg = sub nsw i32 0, %x
192  br i1 %tobool, label %eq_bb, label %done
193
194eq_bb:
195  br label %done
196
197done:
198  %cond = phi i32 [ %y, %eq_bb ], [ %neg, %entry ]
199  ret i32 %cond
200}
201
202; CHECK-LABEL: fold_neg_true_64:
203; CHECK: {{subs.*xzr,|cmp}} x2, #1
204; CHECK-NEXT: csneg x0, x1, x0, eq
205; CHECK-NEXT: ret
206define i64 @fold_neg_true_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
207entry:
208  %tobool = icmp eq i64 %c, 1
209  %neg = sub nsw i64 0, %x
210  br i1 %tobool, label %eq_bb, label %done
211
212eq_bb:
213  br label %done
214
215done:
216  %cond = phi i64 [ %y, %eq_bb ], [ %neg, %entry ]
217  ret i64 %cond
218}
219
220; CHECK-LABEL: fold_neg_false_32:
221; CHECK: {{subs.*wzr,|cmp}} w2, #1
222; CHECK-NEXT: csneg w0, w1, w0, ne
223; CHECK-NEXT: ret
224define i32 @fold_neg_false_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
225entry:
226  %tobool = icmp eq i32 %c, 1
227  %neg = sub nsw i32 0, %x
228  br i1 %tobool, label %eq_bb, label %done
229
230eq_bb:
231  br label %done
232
233done:
234  %cond = phi i32 [ %neg, %eq_bb ], [ %y, %entry ]
235  ret i32 %cond
236}
237
238; CHECK-LABEL: fold_neg_false_64:
239; CHECK: {{subs.*xzr,|cmp}} x2, #1
240; CHECK-NEXT: csneg x0, x1, x0, ne
241; CHECK-NEXT: ret
242define i64 @fold_neg_false_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
243entry:
244  %tobool = icmp eq i64 %c, 1
245  %neg = sub nsw i64 0, %x
246  br i1 %tobool, label %eq_bb, label %done
247
248eq_bb:
249  br label %done
250
251done:
252  %cond = phi i64 [ %neg, %eq_bb ], [ %y, %entry ]
253  ret i64 %cond
254}
255
256; CHECK: cbnz_32
257; CHECK: {{subs.*wzr,|cmp}} w2, #0
258; CHECK-NEXT: csel w0, w1, w0, ne
259; CHECK-NEXT: ret
260define i32 @cbnz_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
261entry:
262  %tobool = icmp eq i32 %c, 0
263  br i1 %tobool, label %eq_bb, label %done
264
265eq_bb:
266  br label %done
267
268done:
269  %cond = phi i32 [ %x, %eq_bb ], [ %y, %entry ]
270  ret i32 %cond
271}
272
273; CHECK: cbnz_64
274; CHECK: {{subs.*xzr,|cmp}} x2, #0
275; CHECK-NEXT: csel x0, x1, x0, ne
276; CHECK-NEXT: ret
277define i64 @cbnz_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
278entry:
279  %tobool = icmp eq i64 %c, 0
280  br i1 %tobool, label %eq_bb, label %done
281
282eq_bb:
283  br label %done
284
285done:
286  %cond = phi i64 [ %x, %eq_bb ], [ %y, %entry ]
287  ret i64 %cond
288}
289
290; CHECK: cbz_32
291; CHECK: {{subs.*wzr,|cmp}} w2, #0
292; CHECK-NEXT: csel w0, w1, w0, eq
293; CHECK-NEXT: ret
294define i32 @cbz_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
295entry:
296  %tobool = icmp ne i32 %c, 0
297  br i1 %tobool, label %ne_bb, label %done
298
299ne_bb:
300  br label %done
301
302done:
303  %cond = phi i32 [ %x, %ne_bb ], [ %y, %entry ]
304  ret i32 %cond
305}
306
307; CHECK: cbz_64
308; CHECK: {{subs.*xzr,|cmp}} x2, #0
309; CHECK-NEXT: csel x0, x1, x0, eq
310; CHECK-NEXT: ret
311define i64 @cbz_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
312entry:
313  %tobool = icmp ne i64 %c, 0
314  br i1 %tobool, label %ne_bb, label %done
315
316ne_bb:
317  br label %done
318
319done:
320  %cond = phi i64 [ %x, %ne_bb ], [ %y, %entry ]
321  ret i64 %cond
322}
323
324; CHECK: tbnz_32
325; CHECK: {{ands.*xzr,|tst}} w2, #0x80
326; CHECK-NEXT: csel w0, w1, w0, ne
327; CHECK-NEXT: ret
328define i32 @tbnz_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
329entry:
330  %mask = and i32 %c, 128
331  %tobool = icmp eq i32 %mask, 0
332  br i1 %tobool, label %eq_bb, label %done
333
334eq_bb:
335  br label %done
336
337done:
338  %cond = phi i32 [ %x, %eq_bb ], [ %y, %entry ]
339  ret i32 %cond
340}
341
342; CHECK: tbnz_64
343; CHECK: {{ands.*xzr,|tst}} x2, #0x8000000000000000
344; CHECK-NEXT: csel x0, x1, x0, ne
345; CHECK-NEXT: ret
346define i64 @tbnz_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
347entry:
348  %mask = and i64 %c, 9223372036854775808
349  %tobool = icmp eq i64 %mask, 0
350  br i1 %tobool, label %eq_bb, label %done
351
352eq_bb:
353  br label %done
354
355done:
356  %cond = phi i64 [ %x, %eq_bb ], [ %y, %entry ]
357  ret i64 %cond
358}
359
360; CHECK: tbz_32
361; CHECK: {{ands.*xzr,|tst}} w2, #0x80
362; CHECK-NEXT: csel w0, w1, w0, eq
363; CHECK-NEXT: ret
364define i32 @tbz_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
365entry:
366  %mask = and i32 %c, 128
367  %tobool = icmp ne i32 %mask, 0
368  br i1 %tobool, label %ne_bb, label %done
369
370ne_bb:
371  br label %done
372
373done:
374  %cond = phi i32 [ %x, %ne_bb ], [ %y, %entry ]
375  ret i32 %cond
376}
377
378; CHECK: tbz_64
379; CHECK: {{ands.*xzr,|tst}} x2, #0x8000000000000000
380; CHECK-NEXT: csel x0, x1, x0, eq
381; CHECK-NEXT: ret
382define i64 @tbz_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
383entry:
384  %mask = and i64 %c, 9223372036854775808
385  %tobool = icmp ne i64 %mask, 0
386  br i1 %tobool, label %ne_bb, label %done
387
388ne_bb:
389  br label %done
390
391done:
392  %cond = phi i64 [ %x, %ne_bb ], [ %y, %entry ]
393  ret i64 %cond
394}
395
396; This function from 175.vpr folds an ADDWri into a CSINC.
397; Remember to clear the kill flag on the ADDWri.
398define i32 @get_ytrack_to_xtracks() nounwind ssp {
399entry:
400  br label %for.body
401
402for.body:
403  %x0 = load i32, i32* undef, align 4
404  br i1 undef, label %if.then.i146, label %is_sbox.exit155
405
406if.then.i146:
407  %add8.i143 = add nsw i32 0, %x0
408  %rem.i144 = srem i32 %add8.i143, %x0
409  %add9.i145 = add i32 %rem.i144, 1
410  br label %is_sbox.exit155
411
412is_sbox.exit155:                                  ; preds = %if.then.i146, %for.body
413  %seg_offset.0.i151 = phi i32 [ %add9.i145, %if.then.i146 ], [ undef, %for.body ]
414  %idxprom15.i152 = sext i32 %seg_offset.0.i151 to i64
415  %arrayidx18.i154 = getelementptr inbounds i32, i32* null, i64 %idxprom15.i152
416  %x1 = load i32, i32* %arrayidx18.i154, align 4
417  br i1 undef, label %for.body51, label %for.body
418
419for.body51:                                       ; preds = %is_sbox.exit155
420  call fastcc void @get_switch_type(i32 %x1, i32 undef, i16 signext undef, i16 signext undef, i16* undef)
421  unreachable
422}
423declare fastcc void @get_switch_type(i32, i32, i16 signext, i16 signext, i16* nocapture) nounwind ssp
424