1 ; RUN: llc < %s -mtriple=arm64 | FileCheck %s
3 define i1 @testSwapCmpWithLSL64_1(i64 %a, i64 %b) {
4 ; CHECK-LABEL testSwapCmpWithLSL64_1:
5 ; CHECK: cmp x1, x0, lsl #1
6 ; CHECK-NEXT: cset w0, gt
9 %cmp = icmp slt i64 %shl, %b
13 define i1 @testSwapCmpWithLSL64_63(i64 %a, i64 %b) {
14 ; CHECK-LABEL testSwapCmpWithLSL64_63:
15 ; CHECK: cmp x1, x0, lsl #63
16 ; CHECK-NEXT: cset w0, gt
19 %cmp = icmp slt i64 %shl, %b
23 define i1 @testSwapCmpWithLSL32_1(i32 %a, i32 %b) {
24 ; CHECK-LABEL testSwapCmpWithLSL32_1:
25 ; CHECK: cmp w1, w0, lsl #1
26 ; CHECK-NEXT: cset w0, gt
29 %cmp = icmp slt i32 %shl, %b
33 define i1 @testSwapCmpWithLSL32_31(i32 %a, i32 %b) {
34 ; CHECK-LABEL testSwapCmpWithLSL32_31:
35 ; CHECK: cmp w1, w0, lsl #31
36 ; CHECK-NEXT: cset w0, gt
39 %cmp = icmp slt i32 %shl, %b
43 define i1 @testSwapCmpWithLSR64_1(i64 %a, i64 %b) {
44 ; CHECK-LABEL testSwapCmpWithLSR64_1:
45 ; CHECK: cmp x1, x0, lsr #1
46 ; CHECK-NEXT: cset w0, gt
48 %lshr = lshr i64 %a, 1
49 %cmp = icmp slt i64 %lshr, %b
53 define i1 @testSwapCmpWithLSR64_63(i64 %a, i64 %b) {
54 ; CHECK-LABEL testSwapCmpWithLSR64_63:
55 ; CHECK: cmp x1, x0, lsr #63
56 ; CHECK-NEXT: cset w0, gt
58 %lshr = lshr i64 %a, 63
59 %cmp = icmp slt i64 %lshr, %b
63 define i1 @testSwapCmpWithLSR32_1(i32 %a, i32 %b) {
64 ; CHECK-LABEL testSwapCmpWithLSR32_1:
65 ; CHECK: cmp w1, w0, lsr #1
66 ; CHECK-NEXT: cset w0, gt
68 %lshr = lshr i32 %a, 1
69 %cmp = icmp slt i32 %lshr, %b
73 define i1 @testSwapCmpWithLSR32_31(i32 %a, i32 %b) {
74 ; CHECK-LABEL testSwapCmpWithLSR32_31:
75 ; CHECK: cmp w1, w0, lsr #31
76 ; CHECK-NEXT: cset w0, gt
78 %lshr = lshr i32 %a, 31
79 %cmp = icmp slt i32 %lshr, %b
83 define i1 @testSwapCmpWithASR64_1(i64 %a, i64 %b) {
84 ; CHECK-LABEL testSwapCmpWithASR64_1:
85 ; CHECK: cmp x1, x0, asr #1
86 ; CHECK-NEXT: cset w0, gt
88 %ashr = ashr i64 %a, 1
89 %cmp = icmp slt i64 %ashr, %b
93 define i1 @testSwapCmpWithASR64_63(i64 %a, i64 %b) {
94 ; CHECK-LABEL testSwapCmpWithASR64_63:
95 ; CHECK: cmp x1, x0, asr #63
96 ; CHECK-NEXT: cset w0, gt
98 %ashr = ashr i64 %a, 63
99 %cmp = icmp slt i64 %ashr, %b
103 define i1 @testSwapCmpWithASR32_1(i32 %a, i32 %b) {
104 ; CHECK-LABEL testSwapCmpWithASR32_1:
105 ; CHECK: cmp w1, w0, asr #1
106 ; CHECK-NEXT: cset w0, gt
108 %ashr = ashr i32 %a, 1
109 %cmp = icmp slt i32 %ashr, %b
113 define i1 @testSwapCmpWithASR32_31(i32 %a, i32 %b) {
114 ; CHECK-LABEL testSwapCmpWithASR32_31:
115 ; CHECK: cmp w1, w0, asr #31
116 ; CHECK-NEXT: cset w0, gt
118 %ashr = ashr i32 %a, 31
119 %cmp = icmp slt i32 %ashr, %b
123 define i1 @testSwapCmpWithShiftedZeroExtend32_64(i32 %a, i64 %b) {
124 ; CHECK-LABEL testSwapCmpWithShiftedZeroExtend32_64
125 ; CHECK: cmp x1, w0, uxtw #2
126 ; CHECK-NEXT: cset w0, lo
128 %a64 = zext i32 %a to i64
129 %shl.0 = shl i64 %a64, 2
130 %cmp = icmp ugt i64 %shl.0, %b
134 define i1 @testSwapCmpWithShiftedZeroExtend16_64(i16 %a, i64 %b) {
135 ; CHECK-LABEL testSwapCmpWithShiftedZeroExtend16_64
136 ; CHECK: cmp x1, w0, uxth #2
137 ; CHECK-NEXT: cset w0, lo
139 %a64 = zext i16 %a to i64
140 %shl.0 = shl i64 %a64, 2
141 %cmp = icmp ugt i64 %shl.0, %b
145 define i1 @testSwapCmpWithShiftedZeroExtend8_64(i8 %a, i64 %b) {
146 ; CHECK-LABEL testSwapCmpWithShiftedZeroExtend8_64
147 ; CHECK: cmp x1, w0, uxtb #4
148 ; CHECK-NEXT: cset w0, lo
150 %a64 = zext i8 %a to i64
151 %shl.2 = shl i64 %a64, 4
152 %cmp = icmp ugt i64 %shl.2, %b
156 define i1 @testSwapCmpWithShiftedZeroExtend16_32(i16 %a, i32 %b) {
157 ; CHECK-LABEL testSwapCmpWithShiftedZeroExtend8_64
158 ; CHECK: cmp w1, w0, uxth #3
159 ; CHECK-NEXT: cset w0, lo
161 %a32 = zext i16 %a to i32
162 %shl = shl i32 %a32, 3
163 %cmp = icmp ugt i32 %shl, %b
167 define i1 @testSwapCmpWithShiftedZeroExtend8_32(i8 %a, i32 %b) {
168 ; CHECK-LABEL testSwapCmpWithShiftedZeroExtend8_64
169 ; CHECK: cmp w1, w0, uxtb #4
170 ; CHECK-NEXT: cset w0, lo
172 %a32 = zext i8 %a to i32
173 %shl = shl i32 %a32, 4
174 %cmp = icmp ugt i32 %shl, %b
178 define i1 @testSwapCmpWithTooLargeShiftedZeroExtend8_32(i8 %a, i32 %b) {
179 ; CHECK-LABEL testSwapCmpWithTooLargeShiftedZeroExtend8_64
180 ; CHECK: and [[REG:w[0-9]+]], w0, #0xff
181 ; CHECK: cmp w1, [[REG]], lsl #5
182 ; CHECK-NEXT: cset w0, lo
184 %a32 = zext i8 %a to i32
185 %shl = shl i32 %a32, 5
186 %cmp = icmp ugt i32 %shl, %b
190 define i1 @testSwapCmpWithZeroExtend8_32(i8 %a, i32 %b) {
191 ; CHECK-LABEL testSwapCmpWithZeroExtend8_64
192 ; CHECK: cmp w1, w0, uxtb
193 ; CHECK-NEXT: cset w0, lo
195 %a32 = zext i8 %a to i32
196 %cmp = icmp ugt i32 %a32, %b
200 define i1 @testSwapCmpWithShiftedSignExtend32_64(i32 %a, i64 %b) {
201 ; CHECK-LABEL testSwapCmpWithShiftedZeroExtend32_64
202 ; CHECK: cmp x1, w0, sxtw #2
203 ; CHECK-NEXT: cset w0, lo
205 %a64 = sext i32 %a to i64
206 %shl.0 = shl i64 %a64, 2
207 %cmp = icmp ugt i64 %shl.0, %b
211 define i1 @testSwapCmpWithShiftedSignExtend16_64(i16 %a, i64 %b) {
212 ; CHECK-LABEL testSwapCmpWithShiftedZeroExtend16_64
213 ; CHECK: cmp x1, w0, sxth #2
214 ; CHECK-NEXT: cset w0, lo
216 %a64 = sext i16 %a to i64
217 %shl.0 = shl i64 %a64, 2
218 %cmp = icmp ugt i64 %shl.0, %b
222 define i1 @testSwapCmpWithShiftedSignExtend8_64(i8 %a, i64 %b) {
223 ; CHECK-LABEL testSwapCmpWithShiftedSignExtend8_64
224 ; CHECK: cmp x1, w0, sxtb #4
225 ; CHECK-NEXT: cset w0, lo
227 %a64 = sext i8 %a to i64
228 %shl.2 = shl i64 %a64, 4
229 %cmp = icmp ugt i64 %shl.2, %b
233 define i1 @testSwapCmpWithShiftedSignExtend16_32(i16 %a, i32 %b) {
234 ; CHECK-LABEL testSwapCmpWithShiftedSignExtend8_64
235 ; CHECK: cmp w1, w0, sxth #3
236 ; CHECK-NEXT: cset w0, lo
238 %a32 = sext i16 %a to i32
239 %shl = shl i32 %a32, 3
240 %cmp = icmp ugt i32 %shl, %b
244 define i1 @testSwapCmpWithShiftedSignExtend8_32(i8 %a, i32 %b) {
245 ; CHECK-LABEL testSwapCmpWithShiftedSignExtend8_64
246 ; CHECK: cmp w1, w0, sxtb #4
247 ; CHECK-NEXT: cset w0, lo
249 %a32 = sext i8 %a to i32
250 %shl = shl i32 %a32, 4
251 %cmp = icmp ugt i32 %shl, %b
255 define i1 @testSwapCmpWithTooLargeShiftedSignExtend8_32(i8 %a, i32 %b) {
256 ; CHECK-LABEL testSwapCmpWithTooLargeShiftedSignExtend8_64
257 ; CHECK: sxtb [[REG:w[0-9]+]], w0
258 ; CHECK-NEXT: cmp w1, [[REG]], lsl #5
259 ; CHECK-NEXT: cset w0, lo
261 %a32 = sext i8 %a to i32
262 %shl = shl i32 %a32, 5
263 %cmp = icmp ugt i32 %shl, %b
267 define i1 @testSwapCmpWithSignExtend8_32(i8 %a, i32 %b) {
268 ; CHECK-LABEL testSwapCmpWithSignExtend8_64
269 ; CHECK: cmp w1, w0, sxtb
270 ; CHECK-NEXT: cset w0, lo
272 %a32 = sext i8 %a to i32
273 %cmp = icmp ugt i32 %a32, %b
277 define i1 @testSwapCmnWithLSL64_1(i64 %a, i64 %b) {
278 ; CHECK-LABEL testSwapCmnWithLSL64_1:
279 ; CHECK: cmn x1, x0, lsl #1
280 ; CHECK-NEXT: cset w0, ne
283 %na = sub i64 0, %shl
284 %cmp = icmp ne i64 %na, %b
288 ; Note: testing with a 62 bits shift as 63 has another optimization kicking in.
289 define i1 @testSwapCmnWithLSL64_62(i64 %a, i64 %b) {
290 ; CHECK-LABEL testSwapCmnWithLSL64_62:
291 ; CHECK: cmn x1, x0, lsl #62
292 ; CHECK-NEXT: cset w0, ne
294 %shl = shl i64 %a, 62
295 %na = sub i64 0, %shl
296 %cmp = icmp ne i64 %na, %b
300 ; Note: the 63 bits shift triggers a different optimization path, which leads
301 ; to a similar result in terms of performances. We try to catch here any change
302 ; so that this test can be adapted should the optimization be done with the
304 define i1 @testSwapCmnWithLSL64_63(i64 %a, i64 %b) {
305 ; CHECK-LABEL testSwapCmnWithLSL64_63:
306 ; CHECK: cmp x1, x0, lsl #63
307 ; CHECK-NEXT: cset w0, ne
309 %shl = shl i64 %a, 63
310 %na = sub i64 0, %shl
311 %cmp = icmp ne i64 %na, %b
315 define i1 @testSwapCmnWithLSL32_1(i32 %a, i32 %b) {
316 ; CHECK-LABEL testSwapCmnWithLSL32_1:
317 ; CHECK: cmn w1, w0, lsl #1
318 ; CHECK-NEXT: cset w0, ne
321 %na = sub i32 0, %shl
322 %cmp = icmp ne i32 %na, %b
326 ; Note: testing with a 30 bits shift as 30 has another optimization kicking in.
327 define i1 @testSwapCmnWithLSL32_30(i32 %a, i32 %b) {
328 ; CHECK-LABEL testSwapCmnWithLSL32_30:
329 ; CHECK: cmn w1, w0, lsl #30
330 ; CHECK-NEXT: cset w0, ne
332 %shl = shl i32 %a, 30
333 %na = sub i32 0, %shl
334 %cmp = icmp ne i32 %na, %b
338 ; Note: the 31 bits shift triggers a different optimization path, which leads
339 ; to a similar result in terms of performances. We try to catch here any change
340 ; so that this test can be adapted should the optimization be done with the
342 define i1 @testSwapCmnWithLSL32_31(i32 %a, i32 %b) {
343 ; CHECK-LABEL testSwapCmnWithLSL32_31:
344 ; CHECK: cmp w1, w0, lsl #31
345 ; CHECK-NEXT: cset w0, ne
347 %shl = shl i32 %a, 31
348 %na = sub i32 0, %shl
349 %cmp = icmp ne i32 %na, %b
353 define i1 @testSwapCmnWithLSR64_1(i64 %a, i64 %b) {
354 ; CHECK-LABEL testSwapCmnWithLSR64_1:
355 ; CHECK: cmn x1, x0, lsr #1
356 ; CHECK-NEXT: cset w0, ne
358 %lshr = lshr i64 %a, 1
359 %na = sub i64 0, %lshr
360 %cmp = icmp ne i64 %na, %b
364 ; Note: testing with a 62 bits shift as 63 has another optimization kicking in.
365 define i1 @testSwapCmnWithLSR64_62(i64 %a, i64 %b) {
366 ; CHECK-LABEL testSwapCmnWithLSR64_62:
367 ; CHECK: cmn x1, x0, lsr #62
368 ; CHECK-NEXT: cset w0, ne
370 %lshr = lshr i64 %a, 62
371 %na = sub i64 0, %lshr
372 %cmp = icmp ne i64 %na, %b
376 ; Note: the 63 bits shift triggers a different optimization path, which leads
377 ; to a similar result in terms of performances. We try to catch here any change
378 ; so that this test can be adapted should the optimization be done with the
380 define i1 @testSwapCmnWithLSR64_63(i64 %a, i64 %b) {
381 ; CHECK-LABEL testSwapCmnWithLSR64_63:
382 ; CHECK: cmp x1, x0, asr #63
383 ; CHECK-NEXT: cset w0, ne
385 %lshr = lshr i64 %a, 63
386 %na = sub i64 0, %lshr
387 %cmp = icmp ne i64 %na, %b
391 define i1 @testSwapCmnWithLSR32_1(i32 %a, i32 %b) {
392 ; CHECK-LABEL testSwapCmnWithLSR32_1:
393 ; CHECK: cmn w1, w0, lsr #1
394 ; CHECK-NEXT: cset w0, ne
396 %lshr = lshr i32 %a, 1
397 %na = sub i32 0, %lshr
398 %cmp = icmp ne i32 %na, %b
402 ; Note: testing with a 30 bits shift as 31 has another optimization kicking in.
403 define i1 @testSwapCmnWithLSR32_30(i32 %a, i32 %b) {
404 ; CHECK-LABEL testSwapCmnWithLSR32_30:
405 ; CHECK: cmn w1, w0, lsr #30
406 ; CHECK-NEXT: cset w0, ne
408 %lshr = lshr i32 %a, 30
409 %na = sub i32 0, %lshr
410 %cmp = icmp ne i32 %na, %b
414 ; Note: the 31 bits shift triggers a different optimization path, which leads
415 ; to a similar result in terms of performances. We try to catch here any change
416 ; so that this test can be adapted should the optimization be done with the
418 define i1 @testSwapCmnWithLSR32_31(i32 %a, i32 %b) {
419 ; CHECK-LABEL testSwapCmnWithLSR32_31:
420 ; CHECK: cmp w1, w0, asr #31
421 ; CHECK-NEXT: cset w0, ne
423 %lshr = lshr i32 %a, 31
424 %na = sub i32 0, %lshr
425 %cmp = icmp ne i32 %na, %b
429 define i1 @testSwapCmnWithASR64_1(i64 %a, i64 %b) {
430 ; CHECK-LABEL testSwapCmnWithASR64_1:
431 ; CHECK: cmn x1, x0, asr #3
432 ; CHECK-NEXT: cset w0, ne
434 %lshr = ashr i64 %a, 3
435 %na = sub i64 0, %lshr
436 %cmp = icmp ne i64 %na, %b
440 ; Note: testing with a 62 bits shift as 63 has another optimization kicking in.
441 define i1 @testSwapCmnWithASR64_62(i64 %a, i64 %b) {
442 ; CHECK-LABEL testSwapCmnWithASR64_62:
443 ; CHECK: cmn x1, x0, asr #62
444 ; CHECK-NEXT: cset w0, ne
446 %lshr = ashr i64 %a, 62
447 %na = sub i64 0, %lshr
448 %cmp = icmp ne i64 %na, %b
452 ; Note: the 63 bits shift triggers a different optimization path, which leads
453 ; to a similar result in terms of performances. We try to catch here any change
454 ; so that this test can be adapted should the optimization be done with the
456 define i1 @testSwapCmnWithASR64_63(i64 %a, i64 %b) {
457 ; CHECK-LABEL testSwapCmnWithASR64_63:
458 ; CHECK: cmp x1, x0, lsr #63
459 ; CHECK-NEXT: cset w0, ne
461 %lshr = ashr i64 %a, 63
462 %na = sub i64 0, %lshr
463 %cmp = icmp ne i64 %na, %b
467 define i1 @testSwapCmnWithASR32_1(i32 %a, i32 %b) {
468 ; CHECK-LABEL testSwapCmnWithASR32_1:
469 ; CHECK: cmn w1, w0, asr #1
470 ; CHECK-NEXT: cset w0, eq
472 %lshr = ashr i32 %a, 1
473 %na = sub i32 0, %lshr
474 %cmp = icmp eq i32 %na, %b
478 ; Note: testing with a 30 bits shift as 31 has another optimization kicking in.
479 define i1 @testSwapCmnWithASR32_30(i32 %a, i32 %b) {
480 ; CHECK-LABEL testSwapCmnWithASR32_30:
481 ; CHECK: cmn w1, w0, asr #30
482 ; CHECK-NEXT: cset w0, ne
484 %lshr = ashr i32 %a, 30
485 %na = sub i32 0, %lshr
486 %cmp = icmp ne i32 %na, %b
490 ; Note: the 31 bits shift triggers a different optimization path, which leads
491 ; to a similar result in terms of performances. We try to catch here any change
492 ; so that this test can be adapted should the optimization be done with the
494 define i1 @testSwapCmnWithASR32_31(i32 %a, i32 %b) {
495 ; CHECK-LABEL testSwapCmnWithASR32_31:
496 ; CHECK: cmp w1, w0, lsr #31
497 ; CHECK-NEXT: cset w0, ne
499 %lshr = ashr i32 %a, 31
500 %na = sub i32 0, %lshr
501 %cmp = icmp ne i32 %na, %b
505 define i64 @testSwapCmpToCmnWithZeroExtend(i32 %a32, i16 %a16, i8 %a8, i64 %b64, i32 %b32) {
506 ; CHECK-LABEL testSwapCmpToCmnWithZeroExtend:
508 %conv0 = zext i32 %a32 to i64
509 %shl0 = shl i64 %conv0, 1
510 %na0 = sub i64 0, %shl0
511 %cmp0 = icmp ne i64 %na0, %b64
512 ; CHECK: cmn x3, w0, uxtw #1
513 br i1 %cmp0, label %t1, label %end
516 %conv1 = zext i16 %a16 to i64
517 %shl1 = shl i64 %conv1, 4
518 %na1 = sub i64 0, %shl1
519 %cmp1 = icmp ne i64 %na1, %b64
520 ; CHECK: cmn x3, w1, uxth #4
521 br i1 %cmp1, label %t2, label %end
524 %conv2 = zext i8 %a8 to i64
525 %shl2 = shl i64 %conv2, 3
526 %na2 = sub i64 0, %shl2
527 %cmp2 = icmp ne i64 %na2, %b64
528 ; CHECK: cmn x3, w2, uxtb #3
529 br i1 %cmp2, label %t3, label %end
532 %conv3 = zext i16 %a16 to i32
533 %shl3 = shl i32 %conv3, 2
534 %na3 = sub i32 0, %shl3
535 %cmp3 = icmp ne i32 %na3, %b32
536 ; CHECK: cmn w4, w1, uxth #2
537 br i1 %cmp3, label %t4, label %end
540 %conv4 = zext i8 %a8 to i32
541 %shl4 = shl i32 %conv4, 1
542 %na4 = sub i32 0, %shl4
543 %cmp4 = icmp ne i32 %na4, %b32
544 ; CHECK: cmn w4, w2, uxtb #1
545 br i1 %cmp4, label %t5, label %end
548 %conv5 = zext i8 %a8 to i32
549 %shl5 = shl i32 %conv5, 5
550 %na5 = sub i32 0, %shl5
551 %cmp5 = icmp ne i32 %na5, %b32
552 ; CHECK: and [[REG:w[0-9]+]], w2, #0xff
553 ; CHECK: cmn w4, [[REG]], lsl #5
554 br i1 %cmp5, label %t6, label %end
557 %conv6 = zext i8 %a8 to i32
558 %na6 = sub i32 0, %conv6
559 %cmp6 = icmp ne i32 %na6, %b32
560 ; CHECK: cmn w4, w2, uxtb
561 br i1 %cmp6, label %t7, label %end
569 define i64 @testSwapCmpToCmnWithSignExtend(i32 %a32, i16 %a16, i8 %a8, i64 %b64, i32 %b32) {
570 ; CHECK-LABEL testSwapCmpToCmnWithSignExtend:
572 %conv0 = sext i32 %a32 to i64
573 %shl0 = shl i64 %conv0, 1
574 %na0 = sub i64 0, %shl0
575 %cmp0 = icmp ne i64 %na0, %b64
576 ; CHECK: cmn x3, w0, sxtw #1
577 br i1 %cmp0, label %t1, label %end
580 %conv1 = sext i16 %a16 to i64
581 %shl1 = shl i64 %conv1, 4
582 %na1 = sub i64 0, %shl1
583 %cmp1 = icmp ne i64 %na1, %b64
584 ; CHECK: cmn x3, w1, sxth #4
585 br i1 %cmp1, label %t2, label %end
588 %conv2 = sext i8 %a8 to i64
589 %shl2 = shl i64 %conv2, 3
590 %na2 = sub i64 0, %shl2
591 %cmp2 = icmp ne i64 %na2, %b64
592 ; CHECK: cmn x3, w2, sxtb #3
593 br i1 %cmp2, label %t3, label %end
596 %conv3 = sext i16 %a16 to i32
597 %shl3 = shl i32 %conv3, 2
598 %na3 = sub i32 0, %shl3
599 %cmp3 = icmp ne i32 %na3, %b32
600 ; CHECK: cmn w4, w1, sxth #2
601 br i1 %cmp3, label %t4, label %end
604 %conv4 = sext i8 %a8 to i32
605 %shl4 = shl i32 %conv4, 1
606 %na4 = sub i32 0, %shl4
607 %cmp4 = icmp ne i32 %na4, %b32
608 ; CHECK: cmn w4, w2, sxtb #1
609 br i1 %cmp4, label %t5, label %end
612 %conv5 = sext i8 %a8 to i32
613 %shl5 = shl i32 %conv5, 5
614 %na5 = sub i32 0, %shl5
615 %cmp5 = icmp ne i32 %na5, %b32
616 ; CHECK: sxtb [[REG:w[0-9]+]], w2
617 ; CHECK: cmn w4, [[REG]], lsl #5
618 br i1 %cmp5, label %t6, label %end
621 %conv6 = sext i8 %a8 to i32
622 %na6 = sub i32 0, %conv6
623 %cmp6 = icmp ne i32 %na6, %b32
624 ; CHECK: cmn w4, w2, sxtb
625 br i1 %cmp6, label %t7, label %end