1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=riscv32-unknown-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,RV32,RV32I
3 ; RUN: llc -mtriple=riscv64-unknown-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,RV64,RV64I
4 ; RUN: llc -mtriple=riscv32-unknown-linux-gnu -mattr=+zbb < %s | FileCheck %s --check-prefixes=CHECK,RV32,RV32ZBB
5 ; RUN: llc -mtriple=riscv64-unknown-linux-gnu -mattr=+zbb < %s | FileCheck %s --check-prefixes=CHECK,RV64,RV64ZBB
7 ; https://bugs.llvm.org/show_bug.cgi?id=38149
9 ; We are truncating from wider width, and then sign-extending
10 ; back to the original width. Then we inequality-comparing orig and src.
11 ; If they don't match, then we had signed truncation during truncation.
13 ; This can be expressed in a several ways in IR:
14 ; trunc + sext + icmp ne <- not canonical
15 ; shl + ashr + icmp ne
18 ; However only the simplest form (with two shifts) gets lowered best.
20 ; ---------------------------------------------------------------------------- ;
21 ; shl + ashr + icmp ne
22 ; ---------------------------------------------------------------------------- ;
24 define i1 @shifts_necmp_i16_i8(i16 %x) nounwind {
25 ; RV32I-LABEL: shifts_necmp_i16_i8:
27 ; RV32I-NEXT: lui a1, 16
28 ; RV32I-NEXT: addi a1, a1, -1
29 ; RV32I-NEXT: and a2, a0, a1
30 ; RV32I-NEXT: slli a0, a0, 24
31 ; RV32I-NEXT: srai a0, a0, 24
32 ; RV32I-NEXT: and a0, a0, a1
33 ; RV32I-NEXT: xor a0, a0, a2
34 ; RV32I-NEXT: snez a0, a0
37 ; RV64I-LABEL: shifts_necmp_i16_i8:
39 ; RV64I-NEXT: lui a1, 16
40 ; RV64I-NEXT: addiw a1, a1, -1
41 ; RV64I-NEXT: and a2, a0, a1
42 ; RV64I-NEXT: slli a0, a0, 56
43 ; RV64I-NEXT: srai a0, a0, 56
44 ; RV64I-NEXT: and a0, a0, a1
45 ; RV64I-NEXT: xor a0, a0, a2
46 ; RV64I-NEXT: snez a0, a0
49 ; RV32ZBB-LABEL: shifts_necmp_i16_i8:
51 ; RV32ZBB-NEXT: zext.h a1, a0
52 ; RV32ZBB-NEXT: sext.b a0, a0
53 ; RV32ZBB-NEXT: zext.h a0, a0
54 ; RV32ZBB-NEXT: xor a0, a0, a1
55 ; RV32ZBB-NEXT: snez a0, a0
58 ; RV64ZBB-LABEL: shifts_necmp_i16_i8:
60 ; RV64ZBB-NEXT: zext.h a1, a0
61 ; RV64ZBB-NEXT: sext.b a0, a0
62 ; RV64ZBB-NEXT: zext.h a0, a0
63 ; RV64ZBB-NEXT: xor a0, a0, a1
64 ; RV64ZBB-NEXT: snez a0, a0
66 %tmp0 = shl i16 %x, 8 ; 16-8
67 %tmp1 = ashr exact i16 %tmp0, 8 ; 16-8
68 %tmp2 = icmp ne i16 %tmp1, %x
72 define i1 @shifts_necmp_i32_i16(i32 %x) nounwind {
73 ; RV32I-LABEL: shifts_necmp_i32_i16:
75 ; RV32I-NEXT: slli a1, a0, 16
76 ; RV32I-NEXT: srai a1, a1, 16
77 ; RV32I-NEXT: xor a0, a1, a0
78 ; RV32I-NEXT: snez a0, a0
81 ; RV64I-LABEL: shifts_necmp_i32_i16:
83 ; RV64I-NEXT: sext.w a1, a0
84 ; RV64I-NEXT: slli a0, a0, 48
85 ; RV64I-NEXT: srai a0, a0, 48
86 ; RV64I-NEXT: xor a0, a0, a1
87 ; RV64I-NEXT: snez a0, a0
90 ; RV32ZBB-LABEL: shifts_necmp_i32_i16:
92 ; RV32ZBB-NEXT: sext.h a1, a0
93 ; RV32ZBB-NEXT: xor a0, a1, a0
94 ; RV32ZBB-NEXT: snez a0, a0
97 ; RV64ZBB-LABEL: shifts_necmp_i32_i16:
99 ; RV64ZBB-NEXT: sext.w a1, a0
100 ; RV64ZBB-NEXT: sext.h a0, a0
101 ; RV64ZBB-NEXT: xor a0, a0, a1
102 ; RV64ZBB-NEXT: snez a0, a0
104 %tmp0 = shl i32 %x, 16 ; 32-16
105 %tmp1 = ashr exact i32 %tmp0, 16 ; 32-16
106 %tmp2 = icmp ne i32 %tmp1, %x
110 define i1 @shifts_necmp_i32_i8(i32 %x) nounwind {
111 ; RV32I-LABEL: shifts_necmp_i32_i8:
113 ; RV32I-NEXT: slli a1, a0, 24
114 ; RV32I-NEXT: srai a1, a1, 24
115 ; RV32I-NEXT: xor a0, a1, a0
116 ; RV32I-NEXT: snez a0, a0
119 ; RV64I-LABEL: shifts_necmp_i32_i8:
121 ; RV64I-NEXT: sext.w a1, a0
122 ; RV64I-NEXT: slli a0, a0, 56
123 ; RV64I-NEXT: srai a0, a0, 56
124 ; RV64I-NEXT: xor a0, a0, a1
125 ; RV64I-NEXT: snez a0, a0
128 ; RV32ZBB-LABEL: shifts_necmp_i32_i8:
130 ; RV32ZBB-NEXT: sext.b a1, a0
131 ; RV32ZBB-NEXT: xor a0, a1, a0
132 ; RV32ZBB-NEXT: snez a0, a0
135 ; RV64ZBB-LABEL: shifts_necmp_i32_i8:
137 ; RV64ZBB-NEXT: sext.w a1, a0
138 ; RV64ZBB-NEXT: sext.b a0, a0
139 ; RV64ZBB-NEXT: xor a0, a0, a1
140 ; RV64ZBB-NEXT: snez a0, a0
142 %tmp0 = shl i32 %x, 24 ; 32-8
143 %tmp1 = ashr exact i32 %tmp0, 24 ; 32-8
144 %tmp2 = icmp ne i32 %tmp1, %x
148 define i1 @shifts_necmp_i64_i32(i64 %x) nounwind {
149 ; RV32-LABEL: shifts_necmp_i64_i32:
151 ; RV32-NEXT: srai a0, a0, 31
152 ; RV32-NEXT: xor a0, a0, a1
153 ; RV32-NEXT: snez a0, a0
156 ; RV64-LABEL: shifts_necmp_i64_i32:
158 ; RV64-NEXT: sext.w a1, a0
159 ; RV64-NEXT: xor a0, a1, a0
160 ; RV64-NEXT: snez a0, a0
162 %tmp0 = shl i64 %x, 32 ; 64-32
163 %tmp1 = ashr exact i64 %tmp0, 32 ; 64-32
164 %tmp2 = icmp ne i64 %tmp1, %x
168 define i1 @shifts_necmp_i64_i16(i64 %x) nounwind {
169 ; RV32I-LABEL: shifts_necmp_i64_i16:
171 ; RV32I-NEXT: slli a2, a0, 16
172 ; RV32I-NEXT: srai a3, a2, 16
173 ; RV32I-NEXT: srai a2, a2, 31
174 ; RV32I-NEXT: xor a1, a2, a1
175 ; RV32I-NEXT: xor a0, a3, a0
176 ; RV32I-NEXT: or a0, a0, a1
177 ; RV32I-NEXT: snez a0, a0
180 ; RV64I-LABEL: shifts_necmp_i64_i16:
182 ; RV64I-NEXT: slli a1, a0, 48
183 ; RV64I-NEXT: srai a1, a1, 48
184 ; RV64I-NEXT: xor a0, a1, a0
185 ; RV64I-NEXT: snez a0, a0
188 ; RV32ZBB-LABEL: shifts_necmp_i64_i16:
190 ; RV32ZBB-NEXT: sext.h a2, a0
191 ; RV32ZBB-NEXT: srai a3, a2, 31
192 ; RV32ZBB-NEXT: xor a0, a2, a0
193 ; RV32ZBB-NEXT: xor a1, a3, a1
194 ; RV32ZBB-NEXT: or a0, a0, a1
195 ; RV32ZBB-NEXT: snez a0, a0
198 ; RV64ZBB-LABEL: shifts_necmp_i64_i16:
200 ; RV64ZBB-NEXT: sext.h a1, a0
201 ; RV64ZBB-NEXT: xor a0, a1, a0
202 ; RV64ZBB-NEXT: snez a0, a0
204 %tmp0 = shl i64 %x, 48 ; 64-16
205 %tmp1 = ashr exact i64 %tmp0, 48 ; 64-16
206 %tmp2 = icmp ne i64 %tmp1, %x
210 define i1 @shifts_necmp_i64_i8(i64 %x) nounwind {
211 ; RV32I-LABEL: shifts_necmp_i64_i8:
213 ; RV32I-NEXT: slli a2, a0, 24
214 ; RV32I-NEXT: srai a3, a2, 24
215 ; RV32I-NEXT: srai a2, a2, 31
216 ; RV32I-NEXT: xor a1, a2, a1
217 ; RV32I-NEXT: xor a0, a3, a0
218 ; RV32I-NEXT: or a0, a0, a1
219 ; RV32I-NEXT: snez a0, a0
222 ; RV64I-LABEL: shifts_necmp_i64_i8:
224 ; RV64I-NEXT: slli a1, a0, 56
225 ; RV64I-NEXT: srai a1, a1, 56
226 ; RV64I-NEXT: xor a0, a1, a0
227 ; RV64I-NEXT: snez a0, a0
230 ; RV32ZBB-LABEL: shifts_necmp_i64_i8:
232 ; RV32ZBB-NEXT: sext.b a2, a0
233 ; RV32ZBB-NEXT: srai a3, a2, 31
234 ; RV32ZBB-NEXT: xor a0, a2, a0
235 ; RV32ZBB-NEXT: xor a1, a3, a1
236 ; RV32ZBB-NEXT: or a0, a0, a1
237 ; RV32ZBB-NEXT: snez a0, a0
240 ; RV64ZBB-LABEL: shifts_necmp_i64_i8:
242 ; RV64ZBB-NEXT: sext.b a1, a0
243 ; RV64ZBB-NEXT: xor a0, a1, a0
244 ; RV64ZBB-NEXT: snez a0, a0
246 %tmp0 = shl i64 %x, 56 ; 64-8
247 %tmp1 = ashr exact i64 %tmp0, 56 ; 64-8
248 %tmp2 = icmp ne i64 %tmp1, %x
252 ; ---------------------------------------------------------------------------- ;
254 ; ---------------------------------------------------------------------------- ;
256 define i1 @add_ultcmp_i16_i8(i16 %x) nounwind {
257 ; RV32I-LABEL: add_ultcmp_i16_i8:
259 ; RV32I-NEXT: slli a0, a0, 16
260 ; RV32I-NEXT: srli a0, a0, 16
261 ; RV32I-NEXT: addi a0, a0, -128
262 ; RV32I-NEXT: srli a0, a0, 8
263 ; RV32I-NEXT: sltiu a0, a0, 255
266 ; RV64I-LABEL: add_ultcmp_i16_i8:
268 ; RV64I-NEXT: slli a0, a0, 48
269 ; RV64I-NEXT: srli a0, a0, 48
270 ; RV64I-NEXT: addi a0, a0, -128
271 ; RV64I-NEXT: srli a0, a0, 8
272 ; RV64I-NEXT: sltiu a0, a0, 255
275 ; RV32ZBB-LABEL: add_ultcmp_i16_i8:
277 ; RV32ZBB-NEXT: zext.h a0, a0
278 ; RV32ZBB-NEXT: addi a0, a0, -128
279 ; RV32ZBB-NEXT: srli a0, a0, 8
280 ; RV32ZBB-NEXT: sltiu a0, a0, 255
283 ; RV64ZBB-LABEL: add_ultcmp_i16_i8:
285 ; RV64ZBB-NEXT: zext.h a0, a0
286 ; RV64ZBB-NEXT: addi a0, a0, -128
287 ; RV64ZBB-NEXT: srli a0, a0, 8
288 ; RV64ZBB-NEXT: sltiu a0, a0, 255
290 %tmp0 = add i16 %x, -128 ; ~0U << (8-1)
291 %tmp1 = icmp ult i16 %tmp0, -256 ; ~0U << 8
295 define i1 @add_ultcmp_i32_i16(i32 %x) nounwind {
296 ; RV32I-LABEL: add_ultcmp_i32_i16:
298 ; RV32I-NEXT: lui a1, 1048568
299 ; RV32I-NEXT: add a0, a0, a1
300 ; RV32I-NEXT: lui a1, 1048560
301 ; RV32I-NEXT: sltu a0, a0, a1
304 ; RV64I-LABEL: add_ultcmp_i32_i16:
306 ; RV64I-NEXT: lui a1, 1048568
307 ; RV64I-NEXT: addw a0, a0, a1
308 ; RV64I-NEXT: lui a1, 1048560
309 ; RV64I-NEXT: sltu a0, a0, a1
312 ; RV32ZBB-LABEL: add_ultcmp_i32_i16:
314 ; RV32ZBB-NEXT: sext.h a1, a0
315 ; RV32ZBB-NEXT: xor a0, a1, a0
316 ; RV32ZBB-NEXT: snez a0, a0
319 ; RV64ZBB-LABEL: add_ultcmp_i32_i16:
321 ; RV64ZBB-NEXT: sext.w a1, a0
322 ; RV64ZBB-NEXT: sext.h a0, a0
323 ; RV64ZBB-NEXT: xor a0, a0, a1
324 ; RV64ZBB-NEXT: snez a0, a0
326 %tmp0 = add i32 %x, -32768 ; ~0U << (16-1)
327 %tmp1 = icmp ult i32 %tmp0, -65536 ; ~0U << 16
331 define i1 @add_ultcmp_i32_i8(i32 %x) nounwind {
332 ; RV32-LABEL: add_ultcmp_i32_i8:
334 ; RV32-NEXT: addi a0, a0, -128
335 ; RV32-NEXT: sltiu a0, a0, -256
338 ; RV64-LABEL: add_ultcmp_i32_i8:
340 ; RV64-NEXT: addiw a0, a0, -128
341 ; RV64-NEXT: sltiu a0, a0, -256
343 %tmp0 = add i32 %x, -128 ; ~0U << (8-1)
344 %tmp1 = icmp ult i32 %tmp0, -256 ; ~0U << 8
348 define i1 @add_ultcmp_i64_i32(i64 %x) nounwind {
349 ; RV32-LABEL: add_ultcmp_i64_i32:
351 ; RV32-NEXT: srai a0, a0, 31
352 ; RV32-NEXT: xor a0, a0, a1
353 ; RV32-NEXT: snez a0, a0
356 ; RV64-LABEL: add_ultcmp_i64_i32:
358 ; RV64-NEXT: sext.w a1, a0
359 ; RV64-NEXT: xor a0, a1, a0
360 ; RV64-NEXT: snez a0, a0
362 %tmp0 = add i64 %x, -2147483648 ; ~0U << (32-1)
363 %tmp1 = icmp ult i64 %tmp0, -4294967296 ; ~0U << 32
367 define i1 @add_ultcmp_i64_i16(i64 %x) nounwind {
368 ; RV32I-LABEL: add_ultcmp_i64_i16:
370 ; RV32I-NEXT: lui a2, 1048568
371 ; RV32I-NEXT: add a2, a0, a2
372 ; RV32I-NEXT: sltu a0, a2, a0
373 ; RV32I-NEXT: add a0, a1, a0
374 ; RV32I-NEXT: lui a1, 1048560
375 ; RV32I-NEXT: sltu a1, a2, a1
376 ; RV32I-NEXT: snez a0, a0
377 ; RV32I-NEXT: or a0, a1, a0
380 ; RV64I-LABEL: add_ultcmp_i64_i16:
382 ; RV64I-NEXT: lui a1, 1048568
383 ; RV64I-NEXT: add a0, a0, a1
384 ; RV64I-NEXT: lui a1, 1048560
385 ; RV64I-NEXT: sltu a0, a0, a1
388 ; RV32ZBB-LABEL: add_ultcmp_i64_i16:
390 ; RV32ZBB-NEXT: sext.h a2, a0
391 ; RV32ZBB-NEXT: xor a0, a2, a0
392 ; RV32ZBB-NEXT: srai a2, a2, 31
393 ; RV32ZBB-NEXT: xor a1, a2, a1
394 ; RV32ZBB-NEXT: or a0, a0, a1
395 ; RV32ZBB-NEXT: snez a0, a0
398 ; RV64ZBB-LABEL: add_ultcmp_i64_i16:
400 ; RV64ZBB-NEXT: sext.h a1, a0
401 ; RV64ZBB-NEXT: xor a0, a1, a0
402 ; RV64ZBB-NEXT: snez a0, a0
404 %tmp0 = add i64 %x, -32768 ; ~0U << (16-1)
405 %tmp1 = icmp ult i64 %tmp0, -65536 ; ~0U << 16
409 define i1 @add_ultcmp_i64_i8(i64 %x) nounwind {
410 ; RV32I-LABEL: add_ultcmp_i64_i8:
412 ; RV32I-NEXT: addi a2, a0, -128
413 ; RV32I-NEXT: sltu a0, a2, a0
414 ; RV32I-NEXT: add a0, a1, a0
415 ; RV32I-NEXT: snez a0, a0
416 ; RV32I-NEXT: sltiu a1, a2, -256
417 ; RV32I-NEXT: or a0, a1, a0
420 ; RV64-LABEL: add_ultcmp_i64_i8:
422 ; RV64-NEXT: addi a0, a0, -128
423 ; RV64-NEXT: sltiu a0, a0, -256
426 ; RV32ZBB-LABEL: add_ultcmp_i64_i8:
428 ; RV32ZBB-NEXT: sext.b a2, a0
429 ; RV32ZBB-NEXT: xor a0, a2, a0
430 ; RV32ZBB-NEXT: srai a2, a2, 31
431 ; RV32ZBB-NEXT: xor a1, a2, a1
432 ; RV32ZBB-NEXT: or a0, a0, a1
433 ; RV32ZBB-NEXT: snez a0, a0
435 %tmp0 = add i64 %x, -128 ; ~0U << (8-1)
436 %tmp1 = icmp ult i64 %tmp0, -256 ; ~0U << 8
440 ; Slightly more canonical variant
441 define i1 @add_ulecmp_i16_i8(i16 %x) nounwind {
442 ; RV32I-LABEL: add_ulecmp_i16_i8:
444 ; RV32I-NEXT: slli a0, a0, 16
445 ; RV32I-NEXT: srli a0, a0, 16
446 ; RV32I-NEXT: addi a0, a0, -128
447 ; RV32I-NEXT: srli a0, a0, 8
448 ; RV32I-NEXT: sltiu a0, a0, 255
451 ; RV64I-LABEL: add_ulecmp_i16_i8:
453 ; RV64I-NEXT: slli a0, a0, 48
454 ; RV64I-NEXT: srli a0, a0, 48
455 ; RV64I-NEXT: addi a0, a0, -128
456 ; RV64I-NEXT: srli a0, a0, 8
457 ; RV64I-NEXT: sltiu a0, a0, 255
460 ; RV32ZBB-LABEL: add_ulecmp_i16_i8:
462 ; RV32ZBB-NEXT: zext.h a0, a0
463 ; RV32ZBB-NEXT: addi a0, a0, -128
464 ; RV32ZBB-NEXT: srli a0, a0, 8
465 ; RV32ZBB-NEXT: sltiu a0, a0, 255
468 ; RV64ZBB-LABEL: add_ulecmp_i16_i8:
470 ; RV64ZBB-NEXT: zext.h a0, a0
471 ; RV64ZBB-NEXT: addi a0, a0, -128
472 ; RV64ZBB-NEXT: srli a0, a0, 8
473 ; RV64ZBB-NEXT: sltiu a0, a0, 255
475 %tmp0 = add i16 %x, -128 ; ~0U << (8-1)
476 %tmp1 = icmp ule i16 %tmp0, -257 ; ~0U << 8 - 1
480 ; ---------------------------------------------------------------------------- ;
482 ; ---------------------------------------------------------------------------- ;
484 define i1 @add_ugecmp_i16_i8(i16 %x) nounwind {
485 ; RV32I-LABEL: add_ugecmp_i16_i8:
487 ; RV32I-NEXT: addi a0, a0, 128
488 ; RV32I-NEXT: slli a0, a0, 16
489 ; RV32I-NEXT: srli a0, a0, 16
490 ; RV32I-NEXT: sltiu a0, a0, 256
491 ; RV32I-NEXT: xori a0, a0, 1
494 ; RV64I-LABEL: add_ugecmp_i16_i8:
496 ; RV64I-NEXT: addi a0, a0, 128
497 ; RV64I-NEXT: slli a0, a0, 48
498 ; RV64I-NEXT: srli a0, a0, 48
499 ; RV64I-NEXT: sltiu a0, a0, 256
500 ; RV64I-NEXT: xori a0, a0, 1
503 ; RV32ZBB-LABEL: add_ugecmp_i16_i8:
505 ; RV32ZBB-NEXT: addi a0, a0, 128
506 ; RV32ZBB-NEXT: zext.h a0, a0
507 ; RV32ZBB-NEXT: sltiu a0, a0, 256
508 ; RV32ZBB-NEXT: xori a0, a0, 1
511 ; RV64ZBB-LABEL: add_ugecmp_i16_i8:
513 ; RV64ZBB-NEXT: addi a0, a0, 128
514 ; RV64ZBB-NEXT: zext.h a0, a0
515 ; RV64ZBB-NEXT: sltiu a0, a0, 256
516 ; RV64ZBB-NEXT: xori a0, a0, 1
518 %tmp0 = add i16 %x, 128 ; 1U << (8-1)
519 %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8
523 define i1 @add_ugecmp_i32_i16(i32 %x) nounwind {
524 ; RV32I-LABEL: add_ugecmp_i32_i16:
526 ; RV32I-NEXT: lui a1, 8
527 ; RV32I-NEXT: add a0, a0, a1
528 ; RV32I-NEXT: srli a0, a0, 16
529 ; RV32I-NEXT: snez a0, a0
532 ; RV64I-LABEL: add_ugecmp_i32_i16:
534 ; RV64I-NEXT: lui a1, 8
535 ; RV64I-NEXT: add a0, a0, a1
536 ; RV64I-NEXT: srliw a0, a0, 16
537 ; RV64I-NEXT: snez a0, a0
540 ; RV32ZBB-LABEL: add_ugecmp_i32_i16:
542 ; RV32ZBB-NEXT: sext.h a1, a0
543 ; RV32ZBB-NEXT: xor a0, a1, a0
544 ; RV32ZBB-NEXT: snez a0, a0
547 ; RV64ZBB-LABEL: add_ugecmp_i32_i16:
549 ; RV64ZBB-NEXT: sext.w a1, a0
550 ; RV64ZBB-NEXT: sext.h a0, a0
551 ; RV64ZBB-NEXT: xor a0, a0, a1
552 ; RV64ZBB-NEXT: snez a0, a0
554 %tmp0 = add i32 %x, 32768 ; 1U << (16-1)
555 %tmp1 = icmp uge i32 %tmp0, 65536 ; 1U << 16
559 define i1 @add_ugecmp_i32_i8(i32 %x) nounwind {
560 ; RV32-LABEL: add_ugecmp_i32_i8:
562 ; RV32-NEXT: addi a0, a0, 128
563 ; RV32-NEXT: sltiu a0, a0, 256
564 ; RV32-NEXT: xori a0, a0, 1
567 ; RV64-LABEL: add_ugecmp_i32_i8:
569 ; RV64-NEXT: addiw a0, a0, 128
570 ; RV64-NEXT: sltiu a0, a0, 256
571 ; RV64-NEXT: xori a0, a0, 1
573 %tmp0 = add i32 %x, 128 ; 1U << (8-1)
574 %tmp1 = icmp uge i32 %tmp0, 256 ; 1U << 8
578 define i1 @add_ugecmp_i64_i32(i64 %x) nounwind {
579 ; RV32-LABEL: add_ugecmp_i64_i32:
581 ; RV32-NEXT: srai a0, a0, 31
582 ; RV32-NEXT: xor a0, a0, a1
583 ; RV32-NEXT: snez a0, a0
586 ; RV64-LABEL: add_ugecmp_i64_i32:
588 ; RV64-NEXT: sext.w a1, a0
589 ; RV64-NEXT: xor a0, a1, a0
590 ; RV64-NEXT: snez a0, a0
592 %tmp0 = add i64 %x, 2147483648 ; 1U << (32-1)
593 %tmp1 = icmp uge i64 %tmp0, 4294967296 ; 1U << 32
597 define i1 @add_ugecmp_i64_i16(i64 %x) nounwind {
598 ; RV32I-LABEL: add_ugecmp_i64_i16:
600 ; RV32I-NEXT: lui a2, 8
601 ; RV32I-NEXT: add a2, a0, a2
602 ; RV32I-NEXT: sltu a0, a2, a0
603 ; RV32I-NEXT: add a0, a1, a0
604 ; RV32I-NEXT: srli a2, a2, 16
605 ; RV32I-NEXT: or a0, a0, a2
606 ; RV32I-NEXT: snez a0, a0
609 ; RV64I-LABEL: add_ugecmp_i64_i16:
611 ; RV64I-NEXT: lui a1, 8
612 ; RV64I-NEXT: add a0, a0, a1
613 ; RV64I-NEXT: srli a0, a0, 16
614 ; RV64I-NEXT: snez a0, a0
617 ; RV32ZBB-LABEL: add_ugecmp_i64_i16:
619 ; RV32ZBB-NEXT: sext.h a2, a0
620 ; RV32ZBB-NEXT: xor a0, a2, a0
621 ; RV32ZBB-NEXT: srai a2, a2, 31
622 ; RV32ZBB-NEXT: xor a1, a2, a1
623 ; RV32ZBB-NEXT: or a0, a0, a1
624 ; RV32ZBB-NEXT: snez a0, a0
627 ; RV64ZBB-LABEL: add_ugecmp_i64_i16:
629 ; RV64ZBB-NEXT: sext.h a1, a0
630 ; RV64ZBB-NEXT: xor a0, a1, a0
631 ; RV64ZBB-NEXT: snez a0, a0
633 %tmp0 = add i64 %x, 32768 ; 1U << (16-1)
634 %tmp1 = icmp uge i64 %tmp0, 65536 ; 1U << 16
638 define i1 @add_ugecmp_i64_i8(i64 %x) nounwind {
639 ; RV32I-LABEL: add_ugecmp_i64_i8:
641 ; RV32I-NEXT: addi a2, a0, 128
642 ; RV32I-NEXT: sltu a0, a2, a0
643 ; RV32I-NEXT: add a0, a1, a0
644 ; RV32I-NEXT: snez a0, a0
645 ; RV32I-NEXT: sltiu a1, a2, 256
646 ; RV32I-NEXT: xori a1, a1, 1
647 ; RV32I-NEXT: or a0, a1, a0
650 ; RV64-LABEL: add_ugecmp_i64_i8:
652 ; RV64-NEXT: addi a0, a0, 128
653 ; RV64-NEXT: sltiu a0, a0, 256
654 ; RV64-NEXT: xori a0, a0, 1
657 ; RV32ZBB-LABEL: add_ugecmp_i64_i8:
659 ; RV32ZBB-NEXT: sext.b a2, a0
660 ; RV32ZBB-NEXT: xor a0, a2, a0
661 ; RV32ZBB-NEXT: srai a2, a2, 31
662 ; RV32ZBB-NEXT: xor a1, a2, a1
663 ; RV32ZBB-NEXT: or a0, a0, a1
664 ; RV32ZBB-NEXT: snez a0, a0
666 %tmp0 = add i64 %x, 128 ; 1U << (8-1)
667 %tmp1 = icmp uge i64 %tmp0, 256 ; 1U << 8
671 ; Slightly more canonical variant
672 define i1 @add_ugtcmp_i16_i8(i16 %x) nounwind {
673 ; RV32I-LABEL: add_ugtcmp_i16_i8:
675 ; RV32I-NEXT: addi a0, a0, 128
676 ; RV32I-NEXT: slli a0, a0, 16
677 ; RV32I-NEXT: srli a0, a0, 16
678 ; RV32I-NEXT: sltiu a0, a0, 256
679 ; RV32I-NEXT: xori a0, a0, 1
682 ; RV64I-LABEL: add_ugtcmp_i16_i8:
684 ; RV64I-NEXT: addi a0, a0, 128
685 ; RV64I-NEXT: slli a0, a0, 48
686 ; RV64I-NEXT: srli a0, a0, 48
687 ; RV64I-NEXT: sltiu a0, a0, 256
688 ; RV64I-NEXT: xori a0, a0, 1
691 ; RV32ZBB-LABEL: add_ugtcmp_i16_i8:
693 ; RV32ZBB-NEXT: addi a0, a0, 128
694 ; RV32ZBB-NEXT: zext.h a0, a0
695 ; RV32ZBB-NEXT: sltiu a0, a0, 256
696 ; RV32ZBB-NEXT: xori a0, a0, 1
699 ; RV64ZBB-LABEL: add_ugtcmp_i16_i8:
701 ; RV64ZBB-NEXT: addi a0, a0, 128
702 ; RV64ZBB-NEXT: zext.h a0, a0
703 ; RV64ZBB-NEXT: sltiu a0, a0, 256
704 ; RV64ZBB-NEXT: xori a0, a0, 1
706 %tmp0 = add i16 %x, 128 ; 1U << (8-1)
707 %tmp1 = icmp ugt i16 %tmp0, 255 ; (1U << 8) - 1
712 ; ---------------------------------------------------------------------------- ;
714 ; Adding not a constant
715 define i1 @add_ugecmp_bad_i16_i8_add(i16 %x, i16 %y) nounwind {
716 ; RV32I-LABEL: add_ugecmp_bad_i16_i8_add:
718 ; RV32I-NEXT: add a0, a0, a1
719 ; RV32I-NEXT: slli a0, a0, 16
720 ; RV32I-NEXT: srli a0, a0, 16
721 ; RV32I-NEXT: sltiu a0, a0, 256
722 ; RV32I-NEXT: xori a0, a0, 1
725 ; RV64I-LABEL: add_ugecmp_bad_i16_i8_add:
727 ; RV64I-NEXT: add a0, a0, a1
728 ; RV64I-NEXT: slli a0, a0, 48
729 ; RV64I-NEXT: srli a0, a0, 48
730 ; RV64I-NEXT: sltiu a0, a0, 256
731 ; RV64I-NEXT: xori a0, a0, 1
734 ; RV32ZBB-LABEL: add_ugecmp_bad_i16_i8_add:
736 ; RV32ZBB-NEXT: add a0, a0, a1
737 ; RV32ZBB-NEXT: zext.h a0, a0
738 ; RV32ZBB-NEXT: sltiu a0, a0, 256
739 ; RV32ZBB-NEXT: xori a0, a0, 1
742 ; RV64ZBB-LABEL: add_ugecmp_bad_i16_i8_add:
744 ; RV64ZBB-NEXT: add a0, a0, a1
745 ; RV64ZBB-NEXT: zext.h a0, a0
746 ; RV64ZBB-NEXT: sltiu a0, a0, 256
747 ; RV64ZBB-NEXT: xori a0, a0, 1
749 %tmp0 = add i16 %x, %y
750 %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8
754 ; Comparing not with a constant
755 define i1 @add_ugecmp_bad_i16_i8_cmp(i16 %x, i16 %y) nounwind {
756 ; RV32I-LABEL: add_ugecmp_bad_i16_i8_cmp:
758 ; RV32I-NEXT: lui a2, 16
759 ; RV32I-NEXT: addi a2, a2, -1
760 ; RV32I-NEXT: and a1, a1, a2
761 ; RV32I-NEXT: addi a0, a0, 128
762 ; RV32I-NEXT: and a0, a0, a2
763 ; RV32I-NEXT: sltu a0, a0, a1
764 ; RV32I-NEXT: xori a0, a0, 1
767 ; RV64I-LABEL: add_ugecmp_bad_i16_i8_cmp:
769 ; RV64I-NEXT: lui a2, 16
770 ; RV64I-NEXT: addiw a2, a2, -1
771 ; RV64I-NEXT: and a1, a1, a2
772 ; RV64I-NEXT: addi a0, a0, 128
773 ; RV64I-NEXT: and a0, a0, a2
774 ; RV64I-NEXT: sltu a0, a0, a1
775 ; RV64I-NEXT: xori a0, a0, 1
778 ; RV32ZBB-LABEL: add_ugecmp_bad_i16_i8_cmp:
780 ; RV32ZBB-NEXT: zext.h a1, a1
781 ; RV32ZBB-NEXT: addi a0, a0, 128
782 ; RV32ZBB-NEXT: zext.h a0, a0
783 ; RV32ZBB-NEXT: sltu a0, a0, a1
784 ; RV32ZBB-NEXT: xori a0, a0, 1
787 ; RV64ZBB-LABEL: add_ugecmp_bad_i16_i8_cmp:
789 ; RV64ZBB-NEXT: zext.h a1, a1
790 ; RV64ZBB-NEXT: addi a0, a0, 128
791 ; RV64ZBB-NEXT: zext.h a0, a0
792 ; RV64ZBB-NEXT: sltu a0, a0, a1
793 ; RV64ZBB-NEXT: xori a0, a0, 1
795 %tmp0 = add i16 %x, 128 ; 1U << (8-1)
796 %tmp1 = icmp uge i16 %tmp0, %y
800 ; Second constant is not larger than the first one
801 define i1 @add_ugecmp_bad_i8_i16(i16 %x) nounwind {
802 ; RV32I-LABEL: add_ugecmp_bad_i8_i16:
804 ; RV32I-NEXT: addi a0, a0, 128
805 ; RV32I-NEXT: slli a0, a0, 16
806 ; RV32I-NEXT: srli a0, a0, 16
807 ; RV32I-NEXT: sltiu a0, a0, 128
808 ; RV32I-NEXT: xori a0, a0, 1
811 ; RV64I-LABEL: add_ugecmp_bad_i8_i16:
813 ; RV64I-NEXT: addi a0, a0, 128
814 ; RV64I-NEXT: slli a0, a0, 48
815 ; RV64I-NEXT: srli a0, a0, 48
816 ; RV64I-NEXT: sltiu a0, a0, 128
817 ; RV64I-NEXT: xori a0, a0, 1
820 ; RV32ZBB-LABEL: add_ugecmp_bad_i8_i16:
822 ; RV32ZBB-NEXT: addi a0, a0, 128
823 ; RV32ZBB-NEXT: zext.h a0, a0
824 ; RV32ZBB-NEXT: sltiu a0, a0, 128
825 ; RV32ZBB-NEXT: xori a0, a0, 1
828 ; RV64ZBB-LABEL: add_ugecmp_bad_i8_i16:
830 ; RV64ZBB-NEXT: addi a0, a0, 128
831 ; RV64ZBB-NEXT: zext.h a0, a0
832 ; RV64ZBB-NEXT: sltiu a0, a0, 128
833 ; RV64ZBB-NEXT: xori a0, a0, 1
835 %tmp0 = add i16 %x, 128 ; 1U << (8-1)
836 %tmp1 = icmp uge i16 %tmp0, 128 ; 1U << (8-1)
840 ; First constant is not power of two
841 define i1 @add_ugecmp_bad_i16_i8_c0notpoweroftwo(i16 %x) nounwind {
842 ; RV32I-LABEL: add_ugecmp_bad_i16_i8_c0notpoweroftwo:
844 ; RV32I-NEXT: addi a0, a0, 192
845 ; RV32I-NEXT: slli a0, a0, 16
846 ; RV32I-NEXT: srli a0, a0, 16
847 ; RV32I-NEXT: sltiu a0, a0, 256
848 ; RV32I-NEXT: xori a0, a0, 1
851 ; RV64I-LABEL: add_ugecmp_bad_i16_i8_c0notpoweroftwo:
853 ; RV64I-NEXT: addi a0, a0, 192
854 ; RV64I-NEXT: slli a0, a0, 48
855 ; RV64I-NEXT: srli a0, a0, 48
856 ; RV64I-NEXT: sltiu a0, a0, 256
857 ; RV64I-NEXT: xori a0, a0, 1
860 ; RV32ZBB-LABEL: add_ugecmp_bad_i16_i8_c0notpoweroftwo:
862 ; RV32ZBB-NEXT: addi a0, a0, 192
863 ; RV32ZBB-NEXT: zext.h a0, a0
864 ; RV32ZBB-NEXT: sltiu a0, a0, 256
865 ; RV32ZBB-NEXT: xori a0, a0, 1
868 ; RV64ZBB-LABEL: add_ugecmp_bad_i16_i8_c0notpoweroftwo:
870 ; RV64ZBB-NEXT: addi a0, a0, 192
871 ; RV64ZBB-NEXT: zext.h a0, a0
872 ; RV64ZBB-NEXT: sltiu a0, a0, 256
873 ; RV64ZBB-NEXT: xori a0, a0, 1
875 %tmp0 = add i16 %x, 192 ; (1U << (8-1)) + (1U << (8-1-1))
876 %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8
880 ; Second constant is not power of two
881 define i1 @add_ugecmp_bad_i16_i8_c1notpoweroftwo(i16 %x) nounwind {
882 ; RV32I-LABEL: add_ugecmp_bad_i16_i8_c1notpoweroftwo:
884 ; RV32I-NEXT: addi a0, a0, 128
885 ; RV32I-NEXT: slli a0, a0, 16
886 ; RV32I-NEXT: srli a0, a0, 16
887 ; RV32I-NEXT: sltiu a0, a0, 768
888 ; RV32I-NEXT: xori a0, a0, 1
891 ; RV64I-LABEL: add_ugecmp_bad_i16_i8_c1notpoweroftwo:
893 ; RV64I-NEXT: addi a0, a0, 128
894 ; RV64I-NEXT: slli a0, a0, 48
895 ; RV64I-NEXT: srli a0, a0, 48
896 ; RV64I-NEXT: sltiu a0, a0, 768
897 ; RV64I-NEXT: xori a0, a0, 1
900 ; RV32ZBB-LABEL: add_ugecmp_bad_i16_i8_c1notpoweroftwo:
902 ; RV32ZBB-NEXT: addi a0, a0, 128
903 ; RV32ZBB-NEXT: zext.h a0, a0
904 ; RV32ZBB-NEXT: sltiu a0, a0, 768
905 ; RV32ZBB-NEXT: xori a0, a0, 1
908 ; RV64ZBB-LABEL: add_ugecmp_bad_i16_i8_c1notpoweroftwo:
910 ; RV64ZBB-NEXT: addi a0, a0, 128
911 ; RV64ZBB-NEXT: zext.h a0, a0
912 ; RV64ZBB-NEXT: sltiu a0, a0, 768
913 ; RV64ZBB-NEXT: xori a0, a0, 1
915 %tmp0 = add i16 %x, 128 ; 1U << (8-1)
916 %tmp1 = icmp uge i16 %tmp0, 768 ; (1U << 8)) + (1U << (8+1))
920 ; Magic check fails, 64 << 1 != 256
921 define i1 @add_ugecmp_bad_i16_i8_magic(i16 %x) nounwind {
922 ; RV32I-LABEL: add_ugecmp_bad_i16_i8_magic:
924 ; RV32I-NEXT: addi a0, a0, 64
925 ; RV32I-NEXT: slli a0, a0, 16
926 ; RV32I-NEXT: srli a0, a0, 16
927 ; RV32I-NEXT: sltiu a0, a0, 256
928 ; RV32I-NEXT: xori a0, a0, 1
931 ; RV64I-LABEL: add_ugecmp_bad_i16_i8_magic:
933 ; RV64I-NEXT: addi a0, a0, 64
934 ; RV64I-NEXT: slli a0, a0, 48
935 ; RV64I-NEXT: srli a0, a0, 48
936 ; RV64I-NEXT: sltiu a0, a0, 256
937 ; RV64I-NEXT: xori a0, a0, 1
940 ; RV32ZBB-LABEL: add_ugecmp_bad_i16_i8_magic:
942 ; RV32ZBB-NEXT: addi a0, a0, 64
943 ; RV32ZBB-NEXT: zext.h a0, a0
944 ; RV32ZBB-NEXT: sltiu a0, a0, 256
945 ; RV32ZBB-NEXT: xori a0, a0, 1
948 ; RV64ZBB-LABEL: add_ugecmp_bad_i16_i8_magic:
950 ; RV64ZBB-NEXT: addi a0, a0, 64
951 ; RV64ZBB-NEXT: zext.h a0, a0
952 ; RV64ZBB-NEXT: sltiu a0, a0, 256
953 ; RV64ZBB-NEXT: xori a0, a0, 1
955 %tmp0 = add i16 %x, 64 ; 1U << (8-1-1)
956 %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8
960 ; Bad 'destination type'
961 define i1 @add_ugecmp_bad_i16_i4(i16 %x) nounwind {
962 ; RV32I-LABEL: add_ugecmp_bad_i16_i4:
964 ; RV32I-NEXT: addi a0, a0, 8
965 ; RV32I-NEXT: slli a0, a0, 16
966 ; RV32I-NEXT: srli a0, a0, 16
967 ; RV32I-NEXT: sltiu a0, a0, 16
968 ; RV32I-NEXT: xori a0, a0, 1
971 ; RV64I-LABEL: add_ugecmp_bad_i16_i4:
973 ; RV64I-NEXT: addi a0, a0, 8
974 ; RV64I-NEXT: slli a0, a0, 48
975 ; RV64I-NEXT: srli a0, a0, 48
976 ; RV64I-NEXT: sltiu a0, a0, 16
977 ; RV64I-NEXT: xori a0, a0, 1
980 ; RV32ZBB-LABEL: add_ugecmp_bad_i16_i4:
982 ; RV32ZBB-NEXT: addi a0, a0, 8
983 ; RV32ZBB-NEXT: zext.h a0, a0
984 ; RV32ZBB-NEXT: sltiu a0, a0, 16
985 ; RV32ZBB-NEXT: xori a0, a0, 1
988 ; RV64ZBB-LABEL: add_ugecmp_bad_i16_i4:
990 ; RV64ZBB-NEXT: addi a0, a0, 8
991 ; RV64ZBB-NEXT: zext.h a0, a0
992 ; RV64ZBB-NEXT: sltiu a0, a0, 16
993 ; RV64ZBB-NEXT: xori a0, a0, 1
995 %tmp0 = add i16 %x, 8 ; 1U << (4-1)
996 %tmp1 = icmp uge i16 %tmp0, 16 ; 1U << 4
1001 define i1 @add_ugecmp_bad_i24_i8(i24 %x) nounwind {
1002 ; RV32-LABEL: add_ugecmp_bad_i24_i8:
1004 ; RV32-NEXT: addi a0, a0, 128
1005 ; RV32-NEXT: slli a0, a0, 8
1006 ; RV32-NEXT: srli a0, a0, 8
1007 ; RV32-NEXT: sltiu a0, a0, 256
1008 ; RV32-NEXT: xori a0, a0, 1
1011 ; RV64-LABEL: add_ugecmp_bad_i24_i8:
1013 ; RV64-NEXT: addi a0, a0, 128
1014 ; RV64-NEXT: slli a0, a0, 40
1015 ; RV64-NEXT: srli a0, a0, 40
1016 ; RV64-NEXT: sltiu a0, a0, 256
1017 ; RV64-NEXT: xori a0, a0, 1
1019 %tmp0 = add i24 %x, 128 ; 1U << (8-1)
1020 %tmp1 = icmp uge i24 %tmp0, 256 ; 1U << 8
1024 ; Slightly more canonical variant
1025 define i1 @add_ugtcmp_bad_i16_i8(i16 %x) nounwind {
1026 ; CHECK-LABEL: add_ugtcmp_bad_i16_i8:
1028 ; CHECK-NEXT: li a0, 0
1030 %tmp0 = add i16 %x, 128 ; 1U << (8-1)
1031 %tmp1 = icmp ugt i16 %tmp0, -1 ; when we +1 it, it will wrap to 0