[ARM] More MVE compare vector splat combines for ANDs
[llvm-complete.git] / test / CodeGen / AArch64 / arm64-early-ifcvt.ll
blobbf5db5058cee90605809ea56eeac986eaab764d2
1 ; RUN: llc < %s -stress-early-ifcvt -aarch64-enable-atomic-cfg-tidy=0 | FileCheck %s
2 target triple = "arm64-apple-macosx"
4 ; CHECK: mm2
5 define i32 @mm2(i32* nocapture %p, i32 %n) nounwind uwtable readonly ssp {
6 entry:
7   br label %do.body
9 ; CHECK: do.body
10 ; Loop body has no branches before the backedge.
11 ; CHECK-NOT: LBB
12 do.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
22 if.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
27 do.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
35 do.end:
36   %sub = sub nsw i32 %max.1, %min.1
37   ret i32 %sub
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
44 define i32 @fold_inc_true_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
45 entry:
46   %tobool = icmp eq i32 %c, 1
47   %inc = add nsw i32 %x, 1
48   br i1 %tobool, label %eq_bb, label %done
50 eq_bb:
51   br label %done
53 done:
54   %cond = phi i32 [ %y, %eq_bb ], [ %inc, %entry ]
55   ret i32 %cond
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
62 define i64 @fold_inc_true_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
63 entry:
64   %tobool = icmp eq i64 %c, 1
65   %inc = add nsw i64 %x, 1
66   br i1 %tobool, label %eq_bb, label %done
68 eq_bb:
69   br label %done
71 done:
72   %cond = phi i64 [ %y, %eq_bb ], [ %inc, %entry ]
73   ret i64 %cond
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
80 define i32 @fold_inc_false_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
81 entry:
82   %tobool = icmp eq i32 %c, 1
83   %inc = add nsw i32 %x, 1
84   br i1 %tobool, label %eq_bb, label %done
86 eq_bb:
87   br label %done
89 done:
90   %cond = phi i32 [ %inc, %eq_bb ], [ %y, %entry ]
91   ret i32 %cond
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
98 define i64 @fold_inc_false_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
99 entry:
100   %tobool = icmp eq i64 %c, 1
101   %inc = add nsw i64 %x, 1
102   br i1 %tobool, label %eq_bb, label %done
104 eq_bb:
105   br label %done
107 done:
108   %cond = phi i64 [ %inc, %eq_bb ], [ %y, %entry ]
109   ret i64 %cond
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
116 define i32 @fold_inv_true_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
117 entry:
118   %tobool = icmp eq i32 %c, 1
119   %inv = xor i32 %x, -1
120   br i1 %tobool, label %eq_bb, label %done
122 eq_bb:
123   br label %done
125 done:
126   %cond = phi i32 [ %y, %eq_bb ], [ %inv, %entry ]
127   ret i32 %cond
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
134 define i64 @fold_inv_true_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
135 entry:
136   %tobool = icmp eq i64 %c, 1
137   %inv = xor i64 %x, -1
138   br i1 %tobool, label %eq_bb, label %done
140 eq_bb:
141   br label %done
143 done:
144   %cond = phi i64 [ %y, %eq_bb ], [ %inv, %entry ]
145   ret i64 %cond
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
152 define i32 @fold_inv_false_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
153 entry:
154   %tobool = icmp eq i32 %c, 1
155   %inv = xor i32 %x, -1
156   br i1 %tobool, label %eq_bb, label %done
158 eq_bb:
159   br label %done
161 done:
162   %cond = phi i32 [ %inv, %eq_bb ], [ %y, %entry ]
163   ret i32 %cond
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
170 define i64 @fold_inv_false_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
171 entry:
172   %tobool = icmp eq i64 %c, 1
173   %inv = xor i64 %x, -1
174   br i1 %tobool, label %eq_bb, label %done
176 eq_bb:
177   br label %done
179 done:
180   %cond = phi i64 [ %inv, %eq_bb ], [ %y, %entry ]
181   ret i64 %cond
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
188 define i32 @fold_neg_true_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
189 entry:
190   %tobool = icmp eq i32 %c, 1
191   %neg = sub nsw i32 0, %x
192   br i1 %tobool, label %eq_bb, label %done
194 eq_bb:
195   br label %done
197 done:
198   %cond = phi i32 [ %y, %eq_bb ], [ %neg, %entry ]
199   ret i32 %cond
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
206 define i64 @fold_neg_true_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
207 entry:
208   %tobool = icmp eq i64 %c, 1
209   %neg = sub nsw i64 0, %x
210   br i1 %tobool, label %eq_bb, label %done
212 eq_bb:
213   br label %done
215 done:
216   %cond = phi i64 [ %y, %eq_bb ], [ %neg, %entry ]
217   ret i64 %cond
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
224 define i32 @fold_neg_false_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
225 entry:
226   %tobool = icmp eq i32 %c, 1
227   %neg = sub nsw i32 0, %x
228   br i1 %tobool, label %eq_bb, label %done
230 eq_bb:
231   br label %done
233 done:
234   %cond = phi i32 [ %neg, %eq_bb ], [ %y, %entry ]
235   ret i32 %cond
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
242 define i64 @fold_neg_false_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
243 entry:
244   %tobool = icmp eq i64 %c, 1
245   %neg = sub nsw i64 0, %x
246   br i1 %tobool, label %eq_bb, label %done
248 eq_bb:
249   br label %done
251 done:
252   %cond = phi i64 [ %neg, %eq_bb ], [ %y, %entry ]
253   ret i64 %cond
256 ; CHECK: cbnz_32
257 ; CHECK: {{subs.*wzr,|cmp}} w2, #0
258 ; CHECK-NEXT: csel w0, w1, w0, ne
259 ; CHECK-NEXT: ret
260 define i32 @cbnz_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
261 entry:
262   %tobool = icmp eq i32 %c, 0
263   br i1 %tobool, label %eq_bb, label %done
265 eq_bb:
266   br label %done
268 done:
269   %cond = phi i32 [ %x, %eq_bb ], [ %y, %entry ]
270   ret i32 %cond
273 ; CHECK: cbnz_64
274 ; CHECK: {{subs.*xzr,|cmp}} x2, #0
275 ; CHECK-NEXT: csel x0, x1, x0, ne
276 ; CHECK-NEXT: ret
277 define i64 @cbnz_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
278 entry:
279   %tobool = icmp eq i64 %c, 0
280   br i1 %tobool, label %eq_bb, label %done
282 eq_bb:
283   br label %done
285 done:
286   %cond = phi i64 [ %x, %eq_bb ], [ %y, %entry ]
287   ret i64 %cond
290 ; CHECK: cbz_32
291 ; CHECK: {{subs.*wzr,|cmp}} w2, #0
292 ; CHECK-NEXT: csel w0, w1, w0, eq
293 ; CHECK-NEXT: ret
294 define i32 @cbz_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
295 entry:
296   %tobool = icmp ne i32 %c, 0
297   br i1 %tobool, label %ne_bb, label %done
299 ne_bb:
300   br label %done
302 done:
303   %cond = phi i32 [ %x, %ne_bb ], [ %y, %entry ]
304   ret i32 %cond
307 ; CHECK: cbz_64
308 ; CHECK: {{subs.*xzr,|cmp}} x2, #0
309 ; CHECK-NEXT: csel x0, x1, x0, eq
310 ; CHECK-NEXT: ret
311 define i64 @cbz_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
312 entry:
313   %tobool = icmp ne i64 %c, 0
314   br i1 %tobool, label %ne_bb, label %done
316 ne_bb:
317   br label %done
319 done:
320   %cond = phi i64 [ %x, %ne_bb ], [ %y, %entry ]
321   ret i64 %cond
324 ; CHECK: tbnz_32
325 ; CHECK: {{ands.*xzr,|tst}} w2, #0x80
326 ; CHECK-NEXT: csel w0, w1, w0, ne
327 ; CHECK-NEXT: ret
328 define i32 @tbnz_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
329 entry:
330   %mask = and i32 %c, 128
331   %tobool = icmp eq i32 %mask, 0
332   br i1 %tobool, label %eq_bb, label %done
334 eq_bb:
335   br label %done
337 done:
338   %cond = phi i32 [ %x, %eq_bb ], [ %y, %entry ]
339   ret i32 %cond
342 ; CHECK: tbnz_64
343 ; CHECK: {{ands.*xzr,|tst}} x2, #0x8000000000000000
344 ; CHECK-NEXT: csel x0, x1, x0, ne
345 ; CHECK-NEXT: ret
346 define i64 @tbnz_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
347 entry:
348   %mask = and i64 %c, 9223372036854775808
349   %tobool = icmp eq i64 %mask, 0
350   br i1 %tobool, label %eq_bb, label %done
352 eq_bb:
353   br label %done
355 done:
356   %cond = phi i64 [ %x, %eq_bb ], [ %y, %entry ]
357   ret i64 %cond
360 ; CHECK: tbz_32
361 ; CHECK: {{ands.*xzr,|tst}} w2, #0x80
362 ; CHECK-NEXT: csel w0, w1, w0, eq
363 ; CHECK-NEXT: ret
364 define i32 @tbz_32(i32 %x, i32 %y, i32 %c) nounwind ssp {
365 entry:
366   %mask = and i32 %c, 128
367   %tobool = icmp ne i32 %mask, 0
368   br i1 %tobool, label %ne_bb, label %done
370 ne_bb:
371   br label %done
373 done:
374   %cond = phi i32 [ %x, %ne_bb ], [ %y, %entry ]
375   ret i32 %cond
378 ; CHECK: tbz_64
379 ; CHECK: {{ands.*xzr,|tst}} x2, #0x8000000000000000
380 ; CHECK-NEXT: csel x0, x1, x0, eq
381 ; CHECK-NEXT: ret
382 define i64 @tbz_64(i64 %x, i64 %y, i64 %c) nounwind ssp {
383 entry:
384   %mask = and i64 %c, 9223372036854775808
385   %tobool = icmp ne i64 %mask, 0
386   br i1 %tobool, label %ne_bb, label %done
388 ne_bb:
389   br label %done
391 done:
392   %cond = phi i64 [ %x, %ne_bb ], [ %y, %entry ]
393   ret i64 %cond
396 ; This function from 175.vpr folds an ADDWri into a CSINC.
397 ; Remember to clear the kill flag on the ADDWri.
398 define i32 @get_ytrack_to_xtracks() nounwind ssp {
399 entry:
400   br label %for.body
402 for.body:
403   %x0 = load i32, i32* undef, align 4
404   br i1 undef, label %if.then.i146, label %is_sbox.exit155
406 if.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
412 is_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
419 for.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
423 declare fastcc void @get_switch_type(i32, i32, i16 signext, i16 signext, i16* nocapture) nounwind ssp