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: slli a1, a0, 16
28 ; RV32I-NEXT: slli a0, a0, 24
29 ; RV32I-NEXT: srli a1, a1, 16
30 ; RV32I-NEXT: srai a0, a0, 8
31 ; RV32I-NEXT: srli a0, a0, 16
32 ; RV32I-NEXT: xor a0, a0, a1
33 ; RV32I-NEXT: snez a0, a0
36 ; RV64I-LABEL: shifts_necmp_i16_i8:
38 ; RV64I-NEXT: slli a1, a0, 48
39 ; RV64I-NEXT: slli a0, a0, 56
40 ; RV64I-NEXT: srli a1, a1, 48
41 ; RV64I-NEXT: srai a0, a0, 8
42 ; RV64I-NEXT: srli a0, a0, 48
43 ; RV64I-NEXT: xor a0, a0, a1
44 ; RV64I-NEXT: snez a0, a0
47 ; RV32ZBB-LABEL: shifts_necmp_i16_i8:
49 ; RV32ZBB-NEXT: zext.h a1, a0
50 ; RV32ZBB-NEXT: sext.b a0, a0
51 ; RV32ZBB-NEXT: zext.h a0, a0
52 ; RV32ZBB-NEXT: xor a0, a0, a1
53 ; RV32ZBB-NEXT: snez a0, a0
56 ; RV64ZBB-LABEL: shifts_necmp_i16_i8:
58 ; RV64ZBB-NEXT: zext.h a1, a0
59 ; RV64ZBB-NEXT: sext.b a0, a0
60 ; RV64ZBB-NEXT: zext.h a0, a0
61 ; RV64ZBB-NEXT: xor a0, a0, a1
62 ; RV64ZBB-NEXT: snez a0, a0
64 %tmp0 = shl i16 %x, 8 ; 16-8
65 %tmp1 = ashr exact i16 %tmp0, 8 ; 16-8
66 %tmp2 = icmp ne i16 %tmp1, %x
70 define i1 @shifts_necmp_i32_i16(i32 %x) nounwind {
71 ; RV32I-LABEL: shifts_necmp_i32_i16:
73 ; RV32I-NEXT: slli a1, a0, 16
74 ; RV32I-NEXT: srai a1, a1, 16
75 ; RV32I-NEXT: xor a0, a1, a0
76 ; RV32I-NEXT: snez a0, a0
79 ; RV64I-LABEL: shifts_necmp_i32_i16:
81 ; RV64I-NEXT: sext.w a1, a0
82 ; RV64I-NEXT: slli a0, a0, 48
83 ; RV64I-NEXT: srai a0, a0, 48
84 ; RV64I-NEXT: xor a0, a0, a1
85 ; RV64I-NEXT: snez a0, a0
88 ; RV32ZBB-LABEL: shifts_necmp_i32_i16:
90 ; RV32ZBB-NEXT: sext.h a1, a0
91 ; RV32ZBB-NEXT: xor a0, a1, a0
92 ; RV32ZBB-NEXT: snez a0, a0
95 ; RV64ZBB-LABEL: shifts_necmp_i32_i16:
97 ; RV64ZBB-NEXT: sext.w a1, a0
98 ; RV64ZBB-NEXT: sext.h a0, a0
99 ; RV64ZBB-NEXT: xor a0, a0, a1
100 ; RV64ZBB-NEXT: snez a0, a0
102 %tmp0 = shl i32 %x, 16 ; 32-16
103 %tmp1 = ashr exact i32 %tmp0, 16 ; 32-16
104 %tmp2 = icmp ne i32 %tmp1, %x
108 define i1 @shifts_necmp_i32_i8(i32 %x) nounwind {
109 ; RV32I-LABEL: shifts_necmp_i32_i8:
111 ; RV32I-NEXT: slli a1, a0, 24
112 ; RV32I-NEXT: srai a1, a1, 24
113 ; RV32I-NEXT: xor a0, a1, a0
114 ; RV32I-NEXT: snez a0, a0
117 ; RV64I-LABEL: shifts_necmp_i32_i8:
119 ; RV64I-NEXT: sext.w a1, a0
120 ; RV64I-NEXT: slli a0, a0, 56
121 ; RV64I-NEXT: srai a0, a0, 56
122 ; RV64I-NEXT: xor a0, a0, a1
123 ; RV64I-NEXT: snez a0, a0
126 ; RV32ZBB-LABEL: shifts_necmp_i32_i8:
128 ; RV32ZBB-NEXT: sext.b a1, a0
129 ; RV32ZBB-NEXT: xor a0, a1, a0
130 ; RV32ZBB-NEXT: snez a0, a0
133 ; RV64ZBB-LABEL: shifts_necmp_i32_i8:
135 ; RV64ZBB-NEXT: sext.w a1, a0
136 ; RV64ZBB-NEXT: sext.b a0, a0
137 ; RV64ZBB-NEXT: xor a0, a0, a1
138 ; RV64ZBB-NEXT: snez a0, a0
140 %tmp0 = shl i32 %x, 24 ; 32-8
141 %tmp1 = ashr exact i32 %tmp0, 24 ; 32-8
142 %tmp2 = icmp ne i32 %tmp1, %x
146 define i1 @shifts_necmp_i64_i32(i64 %x) nounwind {
147 ; RV32-LABEL: shifts_necmp_i64_i32:
149 ; RV32-NEXT: srai a0, a0, 31
150 ; RV32-NEXT: xor a0, a0, a1
151 ; RV32-NEXT: snez a0, a0
154 ; RV64-LABEL: shifts_necmp_i64_i32:
156 ; RV64-NEXT: sext.w a1, a0
157 ; RV64-NEXT: xor a0, a1, a0
158 ; RV64-NEXT: snez a0, a0
160 %tmp0 = shl i64 %x, 32 ; 64-32
161 %tmp1 = ashr exact i64 %tmp0, 32 ; 64-32
162 %tmp2 = icmp ne i64 %tmp1, %x
166 define i1 @shifts_necmp_i64_i16(i64 %x) nounwind {
167 ; RV32I-LABEL: shifts_necmp_i64_i16:
169 ; RV32I-NEXT: slli a2, a0, 16
170 ; RV32I-NEXT: srai a3, a2, 16
171 ; RV32I-NEXT: srai a2, a2, 31
172 ; RV32I-NEXT: xor a1, a2, a1
173 ; RV32I-NEXT: xor a0, a3, a0
174 ; RV32I-NEXT: or a0, a0, a1
175 ; RV32I-NEXT: snez a0, a0
178 ; RV64I-LABEL: shifts_necmp_i64_i16:
180 ; RV64I-NEXT: slli a1, a0, 48
181 ; RV64I-NEXT: srai a1, a1, 48
182 ; RV64I-NEXT: xor a0, a1, a0
183 ; RV64I-NEXT: snez a0, a0
186 ; RV32ZBB-LABEL: shifts_necmp_i64_i16:
188 ; RV32ZBB-NEXT: sext.h a2, a0
189 ; RV32ZBB-NEXT: srai a3, a2, 31
190 ; RV32ZBB-NEXT: xor a0, a2, a0
191 ; RV32ZBB-NEXT: xor a1, a3, a1
192 ; RV32ZBB-NEXT: or a0, a0, a1
193 ; RV32ZBB-NEXT: snez a0, a0
196 ; RV64ZBB-LABEL: shifts_necmp_i64_i16:
198 ; RV64ZBB-NEXT: sext.h a1, a0
199 ; RV64ZBB-NEXT: xor a0, a1, a0
200 ; RV64ZBB-NEXT: snez a0, a0
202 %tmp0 = shl i64 %x, 48 ; 64-16
203 %tmp1 = ashr exact i64 %tmp0, 48 ; 64-16
204 %tmp2 = icmp ne i64 %tmp1, %x
208 define i1 @shifts_necmp_i64_i8(i64 %x) nounwind {
209 ; RV32I-LABEL: shifts_necmp_i64_i8:
211 ; RV32I-NEXT: slli a2, a0, 24
212 ; RV32I-NEXT: srai a3, a2, 24
213 ; RV32I-NEXT: srai a2, a2, 31
214 ; RV32I-NEXT: xor a1, a2, a1
215 ; RV32I-NEXT: xor a0, a3, a0
216 ; RV32I-NEXT: or a0, a0, a1
217 ; RV32I-NEXT: snez a0, a0
220 ; RV64I-LABEL: shifts_necmp_i64_i8:
222 ; RV64I-NEXT: slli a1, a0, 56
223 ; RV64I-NEXT: srai a1, a1, 56
224 ; RV64I-NEXT: xor a0, a1, a0
225 ; RV64I-NEXT: snez a0, a0
228 ; RV32ZBB-LABEL: shifts_necmp_i64_i8:
230 ; RV32ZBB-NEXT: sext.b a2, a0
231 ; RV32ZBB-NEXT: srai a3, a2, 31
232 ; RV32ZBB-NEXT: xor a0, a2, a0
233 ; RV32ZBB-NEXT: xor a1, a3, a1
234 ; RV32ZBB-NEXT: or a0, a0, a1
235 ; RV32ZBB-NEXT: snez a0, a0
238 ; RV64ZBB-LABEL: shifts_necmp_i64_i8:
240 ; RV64ZBB-NEXT: sext.b a1, a0
241 ; RV64ZBB-NEXT: xor a0, a1, a0
242 ; RV64ZBB-NEXT: snez a0, a0
244 %tmp0 = shl i64 %x, 56 ; 64-8
245 %tmp1 = ashr exact i64 %tmp0, 56 ; 64-8
246 %tmp2 = icmp ne i64 %tmp1, %x
250 ; ---------------------------------------------------------------------------- ;
252 ; ---------------------------------------------------------------------------- ;
254 define i1 @add_ultcmp_i16_i8(i16 %x) nounwind {
255 ; RV32I-LABEL: add_ultcmp_i16_i8:
257 ; RV32I-NEXT: slli a0, a0, 16
258 ; RV32I-NEXT: srli a0, a0, 16
259 ; RV32I-NEXT: addi a0, a0, -128
260 ; RV32I-NEXT: srli a0, a0, 8
261 ; RV32I-NEXT: sltiu a0, a0, 255
264 ; RV64I-LABEL: add_ultcmp_i16_i8:
266 ; RV64I-NEXT: slli a0, a0, 48
267 ; RV64I-NEXT: srli a0, a0, 48
268 ; RV64I-NEXT: addi a0, a0, -128
269 ; RV64I-NEXT: srli a0, a0, 8
270 ; RV64I-NEXT: sltiu a0, a0, 255
273 ; RV32ZBB-LABEL: add_ultcmp_i16_i8:
275 ; RV32ZBB-NEXT: zext.h a0, a0
276 ; RV32ZBB-NEXT: addi a0, a0, -128
277 ; RV32ZBB-NEXT: srli a0, a0, 8
278 ; RV32ZBB-NEXT: sltiu a0, a0, 255
281 ; RV64ZBB-LABEL: add_ultcmp_i16_i8:
283 ; RV64ZBB-NEXT: zext.h a0, a0
284 ; RV64ZBB-NEXT: addi a0, a0, -128
285 ; RV64ZBB-NEXT: srli a0, a0, 8
286 ; RV64ZBB-NEXT: sltiu a0, a0, 255
288 %tmp0 = add i16 %x, -128 ; ~0U << (8-1)
289 %tmp1 = icmp ult i16 %tmp0, -256 ; ~0U << 8
293 define i1 @add_ultcmp_i32_i16(i32 %x) nounwind {
294 ; RV32I-LABEL: add_ultcmp_i32_i16:
296 ; RV32I-NEXT: lui a1, 1048568
297 ; RV32I-NEXT: add a0, a0, a1
298 ; RV32I-NEXT: lui a1, 1048560
299 ; RV32I-NEXT: sltu a0, a0, a1
302 ; RV64I-LABEL: add_ultcmp_i32_i16:
304 ; RV64I-NEXT: lui a1, 1048568
305 ; RV64I-NEXT: addw a0, a0, a1
306 ; RV64I-NEXT: lui a1, 1048560
307 ; RV64I-NEXT: sltu a0, a0, a1
310 ; RV32ZBB-LABEL: add_ultcmp_i32_i16:
312 ; RV32ZBB-NEXT: sext.h a1, a0
313 ; RV32ZBB-NEXT: xor a0, a1, a0
314 ; RV32ZBB-NEXT: snez a0, a0
317 ; RV64ZBB-LABEL: add_ultcmp_i32_i16:
319 ; RV64ZBB-NEXT: sext.w a1, a0
320 ; RV64ZBB-NEXT: sext.h a0, a0
321 ; RV64ZBB-NEXT: xor a0, a0, a1
322 ; RV64ZBB-NEXT: snez a0, a0
324 %tmp0 = add i32 %x, -32768 ; ~0U << (16-1)
325 %tmp1 = icmp ult i32 %tmp0, -65536 ; ~0U << 16
329 define i1 @add_ultcmp_i32_i8(i32 %x) nounwind {
330 ; RV32-LABEL: add_ultcmp_i32_i8:
332 ; RV32-NEXT: addi a0, a0, -128
333 ; RV32-NEXT: sltiu a0, a0, -256
336 ; RV64-LABEL: add_ultcmp_i32_i8:
338 ; RV64-NEXT: addiw a0, a0, -128
339 ; RV64-NEXT: sltiu a0, a0, -256
341 %tmp0 = add i32 %x, -128 ; ~0U << (8-1)
342 %tmp1 = icmp ult i32 %tmp0, -256 ; ~0U << 8
346 define i1 @add_ultcmp_i64_i32(i64 %x) nounwind {
347 ; RV32-LABEL: add_ultcmp_i64_i32:
349 ; RV32-NEXT: srai a0, a0, 31
350 ; RV32-NEXT: xor a0, a0, a1
351 ; RV32-NEXT: snez a0, a0
354 ; RV64-LABEL: add_ultcmp_i64_i32:
356 ; RV64-NEXT: sext.w a1, a0
357 ; RV64-NEXT: xor a0, a1, a0
358 ; RV64-NEXT: snez a0, a0
360 %tmp0 = add i64 %x, -2147483648 ; ~0U << (32-1)
361 %tmp1 = icmp ult i64 %tmp0, -4294967296 ; ~0U << 32
365 define i1 @add_ultcmp_i64_i16(i64 %x) nounwind {
366 ; RV32I-LABEL: add_ultcmp_i64_i16:
368 ; RV32I-NEXT: lui a2, 1048568
369 ; RV32I-NEXT: add a2, a0, a2
370 ; RV32I-NEXT: sltu a0, a2, a0
371 ; RV32I-NEXT: add a0, a1, a0
372 ; RV32I-NEXT: lui a1, 1048560
373 ; RV32I-NEXT: sltu a1, a2, a1
374 ; RV32I-NEXT: snez a0, a0
375 ; RV32I-NEXT: or a0, a1, a0
378 ; RV64I-LABEL: add_ultcmp_i64_i16:
380 ; RV64I-NEXT: lui a1, 1048568
381 ; RV64I-NEXT: add a0, a0, a1
382 ; RV64I-NEXT: lui a1, 1048560
383 ; RV64I-NEXT: sltu a0, a0, a1
386 ; RV32ZBB-LABEL: add_ultcmp_i64_i16:
388 ; RV32ZBB-NEXT: sext.h a2, a0
389 ; RV32ZBB-NEXT: xor a0, a2, a0
390 ; RV32ZBB-NEXT: srai a2, a2, 31
391 ; RV32ZBB-NEXT: xor a1, a2, a1
392 ; RV32ZBB-NEXT: or a0, a0, a1
393 ; RV32ZBB-NEXT: snez a0, a0
396 ; RV64ZBB-LABEL: add_ultcmp_i64_i16:
398 ; RV64ZBB-NEXT: sext.h a1, a0
399 ; RV64ZBB-NEXT: xor a0, a1, a0
400 ; RV64ZBB-NEXT: snez a0, a0
402 %tmp0 = add i64 %x, -32768 ; ~0U << (16-1)
403 %tmp1 = icmp ult i64 %tmp0, -65536 ; ~0U << 16
407 define i1 @add_ultcmp_i64_i8(i64 %x) nounwind {
408 ; RV32I-LABEL: add_ultcmp_i64_i8:
410 ; RV32I-NEXT: addi a2, a0, -128
411 ; RV32I-NEXT: sltu a0, a2, a0
412 ; RV32I-NEXT: add a0, a1, a0
413 ; RV32I-NEXT: snez a0, a0
414 ; RV32I-NEXT: sltiu a1, a2, -256
415 ; RV32I-NEXT: or a0, a1, a0
418 ; RV64-LABEL: add_ultcmp_i64_i8:
420 ; RV64-NEXT: addi a0, a0, -128
421 ; RV64-NEXT: sltiu a0, a0, -256
424 ; RV32ZBB-LABEL: add_ultcmp_i64_i8:
426 ; RV32ZBB-NEXT: sext.b a2, a0
427 ; RV32ZBB-NEXT: xor a0, a2, a0
428 ; RV32ZBB-NEXT: srai a2, a2, 31
429 ; RV32ZBB-NEXT: xor a1, a2, a1
430 ; RV32ZBB-NEXT: or a0, a0, a1
431 ; RV32ZBB-NEXT: snez a0, a0
433 %tmp0 = add i64 %x, -128 ; ~0U << (8-1)
434 %tmp1 = icmp ult i64 %tmp0, -256 ; ~0U << 8
438 ; Slightly more canonical variant
439 define i1 @add_ulecmp_i16_i8(i16 %x) nounwind {
440 ; RV32I-LABEL: add_ulecmp_i16_i8:
442 ; RV32I-NEXT: slli a0, a0, 16
443 ; RV32I-NEXT: srli a0, a0, 16
444 ; RV32I-NEXT: addi a0, a0, -128
445 ; RV32I-NEXT: srli a0, a0, 8
446 ; RV32I-NEXT: sltiu a0, a0, 255
449 ; RV64I-LABEL: add_ulecmp_i16_i8:
451 ; RV64I-NEXT: slli a0, a0, 48
452 ; RV64I-NEXT: srli a0, a0, 48
453 ; RV64I-NEXT: addi a0, a0, -128
454 ; RV64I-NEXT: srli a0, a0, 8
455 ; RV64I-NEXT: sltiu a0, a0, 255
458 ; RV32ZBB-LABEL: add_ulecmp_i16_i8:
460 ; RV32ZBB-NEXT: zext.h a0, a0
461 ; RV32ZBB-NEXT: addi a0, a0, -128
462 ; RV32ZBB-NEXT: srli a0, a0, 8
463 ; RV32ZBB-NEXT: sltiu a0, a0, 255
466 ; RV64ZBB-LABEL: add_ulecmp_i16_i8:
468 ; RV64ZBB-NEXT: zext.h a0, a0
469 ; RV64ZBB-NEXT: addi a0, a0, -128
470 ; RV64ZBB-NEXT: srli a0, a0, 8
471 ; RV64ZBB-NEXT: sltiu a0, a0, 255
473 %tmp0 = add i16 %x, -128 ; ~0U << (8-1)
474 %tmp1 = icmp ule i16 %tmp0, -257 ; ~0U << 8 - 1
478 ; ---------------------------------------------------------------------------- ;
480 ; ---------------------------------------------------------------------------- ;
482 define i1 @add_ugecmp_i16_i8(i16 %x) nounwind {
483 ; RV32I-LABEL: add_ugecmp_i16_i8:
485 ; RV32I-NEXT: addi a0, a0, 128
486 ; RV32I-NEXT: slli a0, a0, 16
487 ; RV32I-NEXT: srli a0, a0, 16
488 ; RV32I-NEXT: sltiu a0, a0, 256
489 ; RV32I-NEXT: xori a0, a0, 1
492 ; RV64I-LABEL: add_ugecmp_i16_i8:
494 ; RV64I-NEXT: addi a0, a0, 128
495 ; RV64I-NEXT: slli a0, a0, 48
496 ; RV64I-NEXT: srli a0, a0, 48
497 ; RV64I-NEXT: sltiu a0, a0, 256
498 ; RV64I-NEXT: xori a0, a0, 1
501 ; RV32ZBB-LABEL: add_ugecmp_i16_i8:
503 ; RV32ZBB-NEXT: addi a0, a0, 128
504 ; RV32ZBB-NEXT: zext.h a0, a0
505 ; RV32ZBB-NEXT: sltiu a0, a0, 256
506 ; RV32ZBB-NEXT: xori a0, a0, 1
509 ; RV64ZBB-LABEL: add_ugecmp_i16_i8:
511 ; RV64ZBB-NEXT: addi a0, a0, 128
512 ; RV64ZBB-NEXT: zext.h a0, a0
513 ; RV64ZBB-NEXT: sltiu a0, a0, 256
514 ; RV64ZBB-NEXT: xori a0, a0, 1
516 %tmp0 = add i16 %x, 128 ; 1U << (8-1)
517 %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8
521 define i1 @add_ugecmp_i32_i16(i32 %x) nounwind {
522 ; RV32I-LABEL: add_ugecmp_i32_i16:
524 ; RV32I-NEXT: lui a1, 8
525 ; RV32I-NEXT: add a0, a0, a1
526 ; RV32I-NEXT: srli a0, a0, 16
527 ; RV32I-NEXT: snez a0, a0
530 ; RV64I-LABEL: add_ugecmp_i32_i16:
532 ; RV64I-NEXT: lui a1, 8
533 ; RV64I-NEXT: add a0, a0, a1
534 ; RV64I-NEXT: srliw a0, a0, 16
535 ; RV64I-NEXT: snez a0, a0
538 ; RV32ZBB-LABEL: add_ugecmp_i32_i16:
540 ; RV32ZBB-NEXT: sext.h a1, a0
541 ; RV32ZBB-NEXT: xor a0, a1, a0
542 ; RV32ZBB-NEXT: snez a0, a0
545 ; RV64ZBB-LABEL: add_ugecmp_i32_i16:
547 ; RV64ZBB-NEXT: sext.w a1, a0
548 ; RV64ZBB-NEXT: sext.h a0, a0
549 ; RV64ZBB-NEXT: xor a0, a0, a1
550 ; RV64ZBB-NEXT: snez a0, a0
552 %tmp0 = add i32 %x, 32768 ; 1U << (16-1)
553 %tmp1 = icmp uge i32 %tmp0, 65536 ; 1U << 16
557 define i1 @add_ugecmp_i32_i8(i32 %x) nounwind {
558 ; RV32-LABEL: add_ugecmp_i32_i8:
560 ; RV32-NEXT: addi a0, a0, 128
561 ; RV32-NEXT: sltiu a0, a0, 256
562 ; RV32-NEXT: xori a0, a0, 1
565 ; RV64-LABEL: add_ugecmp_i32_i8:
567 ; RV64-NEXT: addiw a0, a0, 128
568 ; RV64-NEXT: sltiu a0, a0, 256
569 ; RV64-NEXT: xori a0, a0, 1
571 %tmp0 = add i32 %x, 128 ; 1U << (8-1)
572 %tmp1 = icmp uge i32 %tmp0, 256 ; 1U << 8
576 define i1 @add_ugecmp_i64_i32(i64 %x) nounwind {
577 ; RV32-LABEL: add_ugecmp_i64_i32:
579 ; RV32-NEXT: srai a0, a0, 31
580 ; RV32-NEXT: xor a0, a0, a1
581 ; RV32-NEXT: snez a0, a0
584 ; RV64-LABEL: add_ugecmp_i64_i32:
586 ; RV64-NEXT: sext.w a1, a0
587 ; RV64-NEXT: xor a0, a1, a0
588 ; RV64-NEXT: snez a0, a0
590 %tmp0 = add i64 %x, 2147483648 ; 1U << (32-1)
591 %tmp1 = icmp uge i64 %tmp0, 4294967296 ; 1U << 32
595 define i1 @add_ugecmp_i64_i16(i64 %x) nounwind {
596 ; RV32I-LABEL: add_ugecmp_i64_i16:
598 ; RV32I-NEXT: lui a2, 8
599 ; RV32I-NEXT: add a2, a0, a2
600 ; RV32I-NEXT: sltu a0, a2, a0
601 ; RV32I-NEXT: add a0, a1, a0
602 ; RV32I-NEXT: srli a2, a2, 16
603 ; RV32I-NEXT: or a0, a0, a2
604 ; RV32I-NEXT: snez a0, a0
607 ; RV64I-LABEL: add_ugecmp_i64_i16:
609 ; RV64I-NEXT: lui a1, 8
610 ; RV64I-NEXT: add a0, a0, a1
611 ; RV64I-NEXT: srli a0, a0, 16
612 ; RV64I-NEXT: snez a0, a0
615 ; RV32ZBB-LABEL: add_ugecmp_i64_i16:
617 ; RV32ZBB-NEXT: sext.h a2, a0
618 ; RV32ZBB-NEXT: xor a0, a2, a0
619 ; RV32ZBB-NEXT: srai a2, a2, 31
620 ; RV32ZBB-NEXT: xor a1, a2, a1
621 ; RV32ZBB-NEXT: or a0, a0, a1
622 ; RV32ZBB-NEXT: snez a0, a0
625 ; RV64ZBB-LABEL: add_ugecmp_i64_i16:
627 ; RV64ZBB-NEXT: sext.h a1, a0
628 ; RV64ZBB-NEXT: xor a0, a1, a0
629 ; RV64ZBB-NEXT: snez a0, a0
631 %tmp0 = add i64 %x, 32768 ; 1U << (16-1)
632 %tmp1 = icmp uge i64 %tmp0, 65536 ; 1U << 16
636 define i1 @add_ugecmp_i64_i8(i64 %x) nounwind {
637 ; RV32I-LABEL: add_ugecmp_i64_i8:
639 ; RV32I-NEXT: addi a2, a0, 128
640 ; RV32I-NEXT: sltu a0, a2, a0
641 ; RV32I-NEXT: sltiu a2, a2, 256
642 ; RV32I-NEXT: add a0, a1, a0
643 ; RV32I-NEXT: snez a0, a0
644 ; RV32I-NEXT: xori a1, a2, 1
645 ; RV32I-NEXT: or a0, a1, a0
648 ; RV64-LABEL: add_ugecmp_i64_i8:
650 ; RV64-NEXT: addi a0, a0, 128
651 ; RV64-NEXT: sltiu a0, a0, 256
652 ; RV64-NEXT: xori a0, a0, 1
655 ; RV32ZBB-LABEL: add_ugecmp_i64_i8:
657 ; RV32ZBB-NEXT: sext.b a2, a0
658 ; RV32ZBB-NEXT: xor a0, a2, a0
659 ; RV32ZBB-NEXT: srai a2, a2, 31
660 ; RV32ZBB-NEXT: xor a1, a2, a1
661 ; RV32ZBB-NEXT: or a0, a0, a1
662 ; RV32ZBB-NEXT: snez a0, a0
664 %tmp0 = add i64 %x, 128 ; 1U << (8-1)
665 %tmp1 = icmp uge i64 %tmp0, 256 ; 1U << 8
669 ; Slightly more canonical variant
670 define i1 @add_ugtcmp_i16_i8(i16 %x) nounwind {
671 ; RV32I-LABEL: add_ugtcmp_i16_i8:
673 ; RV32I-NEXT: addi a0, a0, 128
674 ; RV32I-NEXT: slli a0, a0, 16
675 ; RV32I-NEXT: srli a0, a0, 16
676 ; RV32I-NEXT: sltiu a0, a0, 256
677 ; RV32I-NEXT: xori a0, a0, 1
680 ; RV64I-LABEL: add_ugtcmp_i16_i8:
682 ; RV64I-NEXT: addi a0, a0, 128
683 ; RV64I-NEXT: slli a0, a0, 48
684 ; RV64I-NEXT: srli a0, a0, 48
685 ; RV64I-NEXT: sltiu a0, a0, 256
686 ; RV64I-NEXT: xori a0, a0, 1
689 ; RV32ZBB-LABEL: add_ugtcmp_i16_i8:
691 ; RV32ZBB-NEXT: addi a0, a0, 128
692 ; RV32ZBB-NEXT: zext.h a0, a0
693 ; RV32ZBB-NEXT: sltiu a0, a0, 256
694 ; RV32ZBB-NEXT: xori a0, a0, 1
697 ; RV64ZBB-LABEL: add_ugtcmp_i16_i8:
699 ; RV64ZBB-NEXT: addi a0, a0, 128
700 ; RV64ZBB-NEXT: zext.h a0, a0
701 ; RV64ZBB-NEXT: sltiu a0, a0, 256
702 ; RV64ZBB-NEXT: xori a0, a0, 1
704 %tmp0 = add i16 %x, 128 ; 1U << (8-1)
705 %tmp1 = icmp ugt i16 %tmp0, 255 ; (1U << 8) - 1
710 ; ---------------------------------------------------------------------------- ;
712 ; Adding not a constant
713 define i1 @add_ugecmp_bad_i16_i8_add(i16 %x, i16 %y) nounwind {
714 ; RV32I-LABEL: add_ugecmp_bad_i16_i8_add:
716 ; RV32I-NEXT: add a0, a0, a1
717 ; RV32I-NEXT: slli a0, a0, 16
718 ; RV32I-NEXT: srli a0, a0, 16
719 ; RV32I-NEXT: sltiu a0, a0, 256
720 ; RV32I-NEXT: xori a0, a0, 1
723 ; RV64I-LABEL: add_ugecmp_bad_i16_i8_add:
725 ; RV64I-NEXT: add a0, a0, a1
726 ; RV64I-NEXT: slli a0, a0, 48
727 ; RV64I-NEXT: srli a0, a0, 48
728 ; RV64I-NEXT: sltiu a0, a0, 256
729 ; RV64I-NEXT: xori a0, a0, 1
732 ; RV32ZBB-LABEL: add_ugecmp_bad_i16_i8_add:
734 ; RV32ZBB-NEXT: add a0, a0, a1
735 ; RV32ZBB-NEXT: zext.h a0, a0
736 ; RV32ZBB-NEXT: sltiu a0, a0, 256
737 ; RV32ZBB-NEXT: xori a0, a0, 1
740 ; RV64ZBB-LABEL: add_ugecmp_bad_i16_i8_add:
742 ; RV64ZBB-NEXT: add a0, a0, a1
743 ; RV64ZBB-NEXT: zext.h a0, a0
744 ; RV64ZBB-NEXT: sltiu a0, a0, 256
745 ; RV64ZBB-NEXT: xori a0, a0, 1
747 %tmp0 = add i16 %x, %y
748 %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8
752 ; Comparing not with a constant
753 define i1 @add_ugecmp_bad_i16_i8_cmp(i16 %x, i16 %y) nounwind {
754 ; RV32I-LABEL: add_ugecmp_bad_i16_i8_cmp:
756 ; RV32I-NEXT: lui a2, 16
757 ; RV32I-NEXT: addi a0, a0, 128
758 ; RV32I-NEXT: addi a2, a2, -1
759 ; RV32I-NEXT: and a1, a1, a2
760 ; RV32I-NEXT: and a0, a0, a2
761 ; RV32I-NEXT: sltu a0, a0, a1
762 ; RV32I-NEXT: xori a0, a0, 1
765 ; RV64I-LABEL: add_ugecmp_bad_i16_i8_cmp:
767 ; RV64I-NEXT: lui a2, 16
768 ; RV64I-NEXT: addi a0, a0, 128
769 ; RV64I-NEXT: addiw a2, a2, -1
770 ; RV64I-NEXT: and a1, a1, a2
771 ; RV64I-NEXT: and a0, a0, a2
772 ; RV64I-NEXT: sltu a0, a0, a1
773 ; RV64I-NEXT: xori a0, a0, 1
776 ; RV32ZBB-LABEL: add_ugecmp_bad_i16_i8_cmp:
778 ; RV32ZBB-NEXT: zext.h a1, a1
779 ; RV32ZBB-NEXT: addi a0, a0, 128
780 ; RV32ZBB-NEXT: zext.h a0, a0
781 ; RV32ZBB-NEXT: sltu a0, a0, a1
782 ; RV32ZBB-NEXT: xori a0, a0, 1
785 ; RV64ZBB-LABEL: add_ugecmp_bad_i16_i8_cmp:
787 ; RV64ZBB-NEXT: zext.h a1, a1
788 ; RV64ZBB-NEXT: addi a0, a0, 128
789 ; RV64ZBB-NEXT: zext.h a0, a0
790 ; RV64ZBB-NEXT: sltu a0, a0, a1
791 ; RV64ZBB-NEXT: xori a0, a0, 1
793 %tmp0 = add i16 %x, 128 ; 1U << (8-1)
794 %tmp1 = icmp uge i16 %tmp0, %y
798 ; Second constant is not larger than the first one
799 define i1 @add_ugecmp_bad_i8_i16(i16 %x) nounwind {
800 ; RV32I-LABEL: add_ugecmp_bad_i8_i16:
802 ; RV32I-NEXT: addi a0, a0, 128
803 ; RV32I-NEXT: slli a0, a0, 16
804 ; RV32I-NEXT: srli a0, a0, 16
805 ; RV32I-NEXT: sltiu a0, a0, 128
806 ; RV32I-NEXT: xori a0, a0, 1
809 ; RV64I-LABEL: add_ugecmp_bad_i8_i16:
811 ; RV64I-NEXT: addi a0, a0, 128
812 ; RV64I-NEXT: slli a0, a0, 48
813 ; RV64I-NEXT: srli a0, a0, 48
814 ; RV64I-NEXT: sltiu a0, a0, 128
815 ; RV64I-NEXT: xori a0, a0, 1
818 ; RV32ZBB-LABEL: add_ugecmp_bad_i8_i16:
820 ; RV32ZBB-NEXT: addi a0, a0, 128
821 ; RV32ZBB-NEXT: zext.h a0, a0
822 ; RV32ZBB-NEXT: sltiu a0, a0, 128
823 ; RV32ZBB-NEXT: xori a0, a0, 1
826 ; RV64ZBB-LABEL: add_ugecmp_bad_i8_i16:
828 ; RV64ZBB-NEXT: addi a0, a0, 128
829 ; RV64ZBB-NEXT: zext.h a0, a0
830 ; RV64ZBB-NEXT: sltiu a0, a0, 128
831 ; RV64ZBB-NEXT: xori a0, a0, 1
833 %tmp0 = add i16 %x, 128 ; 1U << (8-1)
834 %tmp1 = icmp uge i16 %tmp0, 128 ; 1U << (8-1)
838 ; First constant is not power of two
839 define i1 @add_ugecmp_bad_i16_i8_c0notpoweroftwo(i16 %x) nounwind {
840 ; RV32I-LABEL: add_ugecmp_bad_i16_i8_c0notpoweroftwo:
842 ; RV32I-NEXT: addi a0, a0, 192
843 ; RV32I-NEXT: slli a0, a0, 16
844 ; RV32I-NEXT: srli a0, a0, 16
845 ; RV32I-NEXT: sltiu a0, a0, 256
846 ; RV32I-NEXT: xori a0, a0, 1
849 ; RV64I-LABEL: add_ugecmp_bad_i16_i8_c0notpoweroftwo:
851 ; RV64I-NEXT: addi a0, a0, 192
852 ; RV64I-NEXT: slli a0, a0, 48
853 ; RV64I-NEXT: srli a0, a0, 48
854 ; RV64I-NEXT: sltiu a0, a0, 256
855 ; RV64I-NEXT: xori a0, a0, 1
858 ; RV32ZBB-LABEL: add_ugecmp_bad_i16_i8_c0notpoweroftwo:
860 ; RV32ZBB-NEXT: addi a0, a0, 192
861 ; RV32ZBB-NEXT: zext.h a0, a0
862 ; RV32ZBB-NEXT: sltiu a0, a0, 256
863 ; RV32ZBB-NEXT: xori a0, a0, 1
866 ; RV64ZBB-LABEL: add_ugecmp_bad_i16_i8_c0notpoweroftwo:
868 ; RV64ZBB-NEXT: addi a0, a0, 192
869 ; RV64ZBB-NEXT: zext.h a0, a0
870 ; RV64ZBB-NEXT: sltiu a0, a0, 256
871 ; RV64ZBB-NEXT: xori a0, a0, 1
873 %tmp0 = add i16 %x, 192 ; (1U << (8-1)) + (1U << (8-1-1))
874 %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8
878 ; Second constant is not power of two
879 define i1 @add_ugecmp_bad_i16_i8_c1notpoweroftwo(i16 %x) nounwind {
880 ; RV32I-LABEL: add_ugecmp_bad_i16_i8_c1notpoweroftwo:
882 ; RV32I-NEXT: addi a0, a0, 128
883 ; RV32I-NEXT: slli a0, a0, 16
884 ; RV32I-NEXT: srli a0, a0, 16
885 ; RV32I-NEXT: sltiu a0, a0, 768
886 ; RV32I-NEXT: xori a0, a0, 1
889 ; RV64I-LABEL: add_ugecmp_bad_i16_i8_c1notpoweroftwo:
891 ; RV64I-NEXT: addi a0, a0, 128
892 ; RV64I-NEXT: slli a0, a0, 48
893 ; RV64I-NEXT: srli a0, a0, 48
894 ; RV64I-NEXT: sltiu a0, a0, 768
895 ; RV64I-NEXT: xori a0, a0, 1
898 ; RV32ZBB-LABEL: add_ugecmp_bad_i16_i8_c1notpoweroftwo:
900 ; RV32ZBB-NEXT: addi a0, a0, 128
901 ; RV32ZBB-NEXT: zext.h a0, a0
902 ; RV32ZBB-NEXT: sltiu a0, a0, 768
903 ; RV32ZBB-NEXT: xori a0, a0, 1
906 ; RV64ZBB-LABEL: add_ugecmp_bad_i16_i8_c1notpoweroftwo:
908 ; RV64ZBB-NEXT: addi a0, a0, 128
909 ; RV64ZBB-NEXT: zext.h a0, a0
910 ; RV64ZBB-NEXT: sltiu a0, a0, 768
911 ; RV64ZBB-NEXT: xori a0, a0, 1
913 %tmp0 = add i16 %x, 128 ; 1U << (8-1)
914 %tmp1 = icmp uge i16 %tmp0, 768 ; (1U << 8)) + (1U << (8+1))
918 ; Magic check fails, 64 << 1 != 256
919 define i1 @add_ugecmp_bad_i16_i8_magic(i16 %x) nounwind {
920 ; RV32I-LABEL: add_ugecmp_bad_i16_i8_magic:
922 ; RV32I-NEXT: addi a0, a0, 64
923 ; RV32I-NEXT: slli a0, a0, 16
924 ; RV32I-NEXT: srli a0, a0, 16
925 ; RV32I-NEXT: sltiu a0, a0, 256
926 ; RV32I-NEXT: xori a0, a0, 1
929 ; RV64I-LABEL: add_ugecmp_bad_i16_i8_magic:
931 ; RV64I-NEXT: addi a0, a0, 64
932 ; RV64I-NEXT: slli a0, a0, 48
933 ; RV64I-NEXT: srli a0, a0, 48
934 ; RV64I-NEXT: sltiu a0, a0, 256
935 ; RV64I-NEXT: xori a0, a0, 1
938 ; RV32ZBB-LABEL: add_ugecmp_bad_i16_i8_magic:
940 ; RV32ZBB-NEXT: addi a0, a0, 64
941 ; RV32ZBB-NEXT: zext.h a0, a0
942 ; RV32ZBB-NEXT: sltiu a0, a0, 256
943 ; RV32ZBB-NEXT: xori a0, a0, 1
946 ; RV64ZBB-LABEL: add_ugecmp_bad_i16_i8_magic:
948 ; RV64ZBB-NEXT: addi a0, a0, 64
949 ; RV64ZBB-NEXT: zext.h a0, a0
950 ; RV64ZBB-NEXT: sltiu a0, a0, 256
951 ; RV64ZBB-NEXT: xori a0, a0, 1
953 %tmp0 = add i16 %x, 64 ; 1U << (8-1-1)
954 %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8
958 ; Bad 'destination type'
959 define i1 @add_ugecmp_bad_i16_i4(i16 %x) nounwind {
960 ; RV32I-LABEL: add_ugecmp_bad_i16_i4:
962 ; RV32I-NEXT: addi a0, a0, 8
963 ; RV32I-NEXT: slli a0, a0, 16
964 ; RV32I-NEXT: srli a0, a0, 16
965 ; RV32I-NEXT: sltiu a0, a0, 16
966 ; RV32I-NEXT: xori a0, a0, 1
969 ; RV64I-LABEL: add_ugecmp_bad_i16_i4:
971 ; RV64I-NEXT: addi a0, a0, 8
972 ; RV64I-NEXT: slli a0, a0, 48
973 ; RV64I-NEXT: srli a0, a0, 48
974 ; RV64I-NEXT: sltiu a0, a0, 16
975 ; RV64I-NEXT: xori a0, a0, 1
978 ; RV32ZBB-LABEL: add_ugecmp_bad_i16_i4:
980 ; RV32ZBB-NEXT: addi a0, a0, 8
981 ; RV32ZBB-NEXT: zext.h a0, a0
982 ; RV32ZBB-NEXT: sltiu a0, a0, 16
983 ; RV32ZBB-NEXT: xori a0, a0, 1
986 ; RV64ZBB-LABEL: add_ugecmp_bad_i16_i4:
988 ; RV64ZBB-NEXT: addi a0, a0, 8
989 ; RV64ZBB-NEXT: zext.h a0, a0
990 ; RV64ZBB-NEXT: sltiu a0, a0, 16
991 ; RV64ZBB-NEXT: xori a0, a0, 1
993 %tmp0 = add i16 %x, 8 ; 1U << (4-1)
994 %tmp1 = icmp uge i16 %tmp0, 16 ; 1U << 4
999 define i1 @add_ugecmp_bad_i24_i8(i24 %x) nounwind {
1000 ; RV32-LABEL: add_ugecmp_bad_i24_i8:
1002 ; RV32-NEXT: addi a0, a0, 128
1003 ; RV32-NEXT: slli a0, a0, 8
1004 ; RV32-NEXT: srli a0, a0, 8
1005 ; RV32-NEXT: sltiu a0, a0, 256
1006 ; RV32-NEXT: xori a0, a0, 1
1009 ; RV64-LABEL: add_ugecmp_bad_i24_i8:
1011 ; RV64-NEXT: addi a0, a0, 128
1012 ; RV64-NEXT: slli a0, a0, 40
1013 ; RV64-NEXT: srli a0, a0, 40
1014 ; RV64-NEXT: sltiu a0, a0, 256
1015 ; RV64-NEXT: xori a0, a0, 1
1017 %tmp0 = add i24 %x, 128 ; 1U << (8-1)
1018 %tmp1 = icmp uge i24 %tmp0, 256 ; 1U << 8
1022 ; Slightly more canonical variant
1023 define i1 @add_ugtcmp_bad_i16_i8(i16 %x) nounwind {
1024 ; CHECK-LABEL: add_ugtcmp_bad_i16_i8:
1026 ; CHECK-NEXT: li a0, 0
1028 %tmp0 = add i16 %x, 128 ; 1U << (8-1)
1029 %tmp1 = icmp ugt i16 %tmp0, -1 ; when we +1 it, it will wrap to 0