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 equality-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 eq <- not canonical
15 ; shl + ashr + icmp eq
18 ; However only the simplest form (with two shifts) gets lowered best.
20 ; ---------------------------------------------------------------------------- ;
21 ; shl + ashr + icmp eq
22 ; ---------------------------------------------------------------------------- ;
24 define i1 @shifts_eqcmp_i16_i8(i16 %x) nounwind {
25 ; RV32I-LABEL: shifts_eqcmp_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: seqz a0, a0
37 ; RV64I-LABEL: shifts_eqcmp_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: seqz a0, a0
49 ; RV32ZBB-LABEL: shifts_eqcmp_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: seqz a0, a0
58 ; RV64ZBB-LABEL: shifts_eqcmp_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: seqz a0, a0
66 %tmp0 = shl i16 %x, 8 ; 16-8
67 %tmp1 = ashr exact i16 %tmp0, 8 ; 16-8
68 %tmp2 = icmp eq i16 %tmp1, %x
72 define i1 @shifts_eqcmp_i32_i16(i32 %x) nounwind {
73 ; RV32I-LABEL: shifts_eqcmp_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: seqz a0, a0
81 ; RV64I-LABEL: shifts_eqcmp_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: seqz a0, a0
90 ; RV32ZBB-LABEL: shifts_eqcmp_i32_i16:
92 ; RV32ZBB-NEXT: sext.h a1, a0
93 ; RV32ZBB-NEXT: xor a0, a1, a0
94 ; RV32ZBB-NEXT: seqz a0, a0
97 ; RV64ZBB-LABEL: shifts_eqcmp_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: seqz a0, a0
104 %tmp0 = shl i32 %x, 16 ; 32-16
105 %tmp1 = ashr exact i32 %tmp0, 16 ; 32-16
106 %tmp2 = icmp eq i32 %tmp1, %x
110 define i1 @shifts_eqcmp_i32_i8(i32 %x) nounwind {
111 ; RV32I-LABEL: shifts_eqcmp_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: seqz a0, a0
119 ; RV64I-LABEL: shifts_eqcmp_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: seqz a0, a0
128 ; RV32ZBB-LABEL: shifts_eqcmp_i32_i8:
130 ; RV32ZBB-NEXT: sext.b a1, a0
131 ; RV32ZBB-NEXT: xor a0, a1, a0
132 ; RV32ZBB-NEXT: seqz a0, a0
135 ; RV64ZBB-LABEL: shifts_eqcmp_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: seqz a0, a0
142 %tmp0 = shl i32 %x, 24 ; 32-8
143 %tmp1 = ashr exact i32 %tmp0, 24 ; 32-8
144 %tmp2 = icmp eq i32 %tmp1, %x
148 define i1 @shifts_eqcmp_i64_i32(i64 %x) nounwind {
149 ; RV32-LABEL: shifts_eqcmp_i64_i32:
151 ; RV32-NEXT: srai a0, a0, 31
152 ; RV32-NEXT: xor a0, a0, a1
153 ; RV32-NEXT: seqz a0, a0
156 ; RV64-LABEL: shifts_eqcmp_i64_i32:
158 ; RV64-NEXT: sext.w a1, a0
159 ; RV64-NEXT: xor a0, a1, a0
160 ; RV64-NEXT: seqz a0, a0
162 %tmp0 = shl i64 %x, 32 ; 64-32
163 %tmp1 = ashr exact i64 %tmp0, 32 ; 64-32
164 %tmp2 = icmp eq i64 %tmp1, %x
168 define i1 @shifts_eqcmp_i64_i16(i64 %x) nounwind {
169 ; RV32I-LABEL: shifts_eqcmp_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: seqz a0, a0
180 ; RV64I-LABEL: shifts_eqcmp_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: seqz a0, a0
188 ; RV32ZBB-LABEL: shifts_eqcmp_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: seqz a0, a0
198 ; RV64ZBB-LABEL: shifts_eqcmp_i64_i16:
200 ; RV64ZBB-NEXT: sext.h a1, a0
201 ; RV64ZBB-NEXT: xor a0, a1, a0
202 ; RV64ZBB-NEXT: seqz a0, a0
204 %tmp0 = shl i64 %x, 48 ; 64-16
205 %tmp1 = ashr exact i64 %tmp0, 48 ; 64-16
206 %tmp2 = icmp eq i64 %tmp1, %x
210 define i1 @shifts_eqcmp_i64_i8(i64 %x) nounwind {
211 ; RV32I-LABEL: shifts_eqcmp_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: seqz a0, a0
222 ; RV64I-LABEL: shifts_eqcmp_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: seqz a0, a0
230 ; RV32ZBB-LABEL: shifts_eqcmp_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: seqz a0, a0
240 ; RV64ZBB-LABEL: shifts_eqcmp_i64_i8:
242 ; RV64ZBB-NEXT: sext.b a1, a0
243 ; RV64ZBB-NEXT: xor a0, a1, a0
244 ; RV64ZBB-NEXT: seqz a0, a0
246 %tmp0 = shl i64 %x, 56 ; 64-8
247 %tmp1 = ashr exact i64 %tmp0, 56 ; 64-8
248 %tmp2 = icmp eq i64 %tmp1, %x
252 ; ---------------------------------------------------------------------------- ;
254 ; ---------------------------------------------------------------------------- ;
256 define i1 @add_ugecmp_i16_i8(i16 %x) nounwind {
257 ; RV32-LABEL: add_ugecmp_i16_i8:
259 ; RV32-NEXT: addi a0, a0, -128
260 ; RV32-NEXT: slli a0, a0, 16
261 ; RV32-NEXT: srli a0, a0, 24
262 ; RV32-NEXT: sltiu a0, a0, 255
263 ; RV32-NEXT: xori a0, a0, 1
266 ; RV64-LABEL: add_ugecmp_i16_i8:
268 ; RV64-NEXT: addi a0, a0, -128
269 ; RV64-NEXT: slli a0, a0, 48
270 ; RV64-NEXT: srli a0, a0, 56
271 ; RV64-NEXT: sltiu a0, a0, 255
272 ; RV64-NEXT: xori a0, a0, 1
274 %tmp0 = add i16 %x, -128 ; ~0U << (8-1)
275 %tmp1 = icmp uge i16 %tmp0, -256 ; ~0U << 8
279 define i1 @add_ugecmp_i32_i16_i8(i16 %xx) nounwind {
280 ; RV32I-LABEL: add_ugecmp_i32_i16_i8:
282 ; RV32I-NEXT: slli a0, a0, 16
283 ; RV32I-NEXT: srli a0, a0, 16
284 ; RV32I-NEXT: addi a0, a0, -128
285 ; RV32I-NEXT: sltiu a0, a0, -256
286 ; RV32I-NEXT: xori a0, a0, 1
289 ; RV64I-LABEL: add_ugecmp_i32_i16_i8:
291 ; RV64I-NEXT: slli a0, a0, 48
292 ; RV64I-NEXT: srli a0, a0, 48
293 ; RV64I-NEXT: addi a0, a0, -128
294 ; RV64I-NEXT: sltiu a0, a0, -256
295 ; RV64I-NEXT: xori a0, a0, 1
298 ; RV32ZBB-LABEL: add_ugecmp_i32_i16_i8:
300 ; RV32ZBB-NEXT: zext.h a0, a0
301 ; RV32ZBB-NEXT: addi a0, a0, -128
302 ; RV32ZBB-NEXT: sltiu a0, a0, -256
303 ; RV32ZBB-NEXT: xori a0, a0, 1
306 ; RV64ZBB-LABEL: add_ugecmp_i32_i16_i8:
308 ; RV64ZBB-NEXT: zext.h a0, a0
309 ; RV64ZBB-NEXT: addi a0, a0, -128
310 ; RV64ZBB-NEXT: sltiu a0, a0, -256
311 ; RV64ZBB-NEXT: xori a0, a0, 1
313 %x = zext i16 %xx to i32
314 %tmp0 = add i32 %x, -128 ; ~0U << (8-1)
315 %tmp1 = icmp uge i32 %tmp0, -256 ; ~0U << 8
319 define i1 @add_ugecmp_i32_i16(i32 %x) nounwind {
320 ; RV32I-LABEL: add_ugecmp_i32_i16:
322 ; RV32I-NEXT: lui a1, 1048568
323 ; RV32I-NEXT: add a0, a0, a1
324 ; RV32I-NEXT: lui a1, 1048560
325 ; RV32I-NEXT: addi a1, a1, -1
326 ; RV32I-NEXT: sltu a0, a1, a0
329 ; RV64I-LABEL: add_ugecmp_i32_i16:
331 ; RV64I-NEXT: lui a1, 1048568
332 ; RV64I-NEXT: addw a0, a0, a1
333 ; RV64I-NEXT: lui a1, 1048560
334 ; RV64I-NEXT: addiw a1, a1, -1
335 ; RV64I-NEXT: sltu a0, a1, a0
338 ; RV32ZBB-LABEL: add_ugecmp_i32_i16:
340 ; RV32ZBB-NEXT: sext.h a1, a0
341 ; RV32ZBB-NEXT: xor a0, a1, a0
342 ; RV32ZBB-NEXT: seqz a0, a0
345 ; RV64ZBB-LABEL: add_ugecmp_i32_i16:
347 ; RV64ZBB-NEXT: sext.w a1, a0
348 ; RV64ZBB-NEXT: sext.h a0, a0
349 ; RV64ZBB-NEXT: xor a0, a0, a1
350 ; RV64ZBB-NEXT: seqz a0, a0
352 %tmp0 = add i32 %x, -32768 ; ~0U << (16-1)
353 %tmp1 = icmp uge i32 %tmp0, -65536 ; ~0U << 16
357 define i1 @add_ugecmp_i32_i8(i32 %x) nounwind {
358 ; RV32-LABEL: add_ugecmp_i32_i8:
360 ; RV32-NEXT: addi a0, a0, -128
361 ; RV32-NEXT: sltiu a0, a0, -256
362 ; RV32-NEXT: xori a0, a0, 1
365 ; RV64-LABEL: add_ugecmp_i32_i8:
367 ; RV64-NEXT: addiw a0, a0, -128
368 ; RV64-NEXT: sltiu a0, a0, -256
369 ; RV64-NEXT: xori a0, a0, 1
371 %tmp0 = add i32 %x, -128 ; ~0U << (8-1)
372 %tmp1 = icmp uge i32 %tmp0, -256 ; ~0U << 8
376 define i1 @add_ugecmp_i64_i32(i64 %x) nounwind {
377 ; RV32-LABEL: add_ugecmp_i64_i32:
379 ; RV32-NEXT: srai a0, a0, 31
380 ; RV32-NEXT: xor a0, a0, a1
381 ; RV32-NEXT: seqz a0, a0
384 ; RV64-LABEL: add_ugecmp_i64_i32:
386 ; RV64-NEXT: sext.w a1, a0
387 ; RV64-NEXT: xor a0, a1, a0
388 ; RV64-NEXT: seqz a0, a0
390 %tmp0 = add i64 %x, -2147483648 ; ~0U << (32-1)
391 %tmp1 = icmp uge i64 %tmp0, -4294967296 ; ~0U << 32
395 define i1 @add_ugecmp_i64_i16(i64 %x) nounwind {
396 ; RV32I-LABEL: add_ugecmp_i64_i16:
398 ; RV32I-NEXT: lui a2, 1048568
399 ; RV32I-NEXT: add a2, a0, a2
400 ; RV32I-NEXT: sltu a0, a2, a0
401 ; RV32I-NEXT: add a0, a1, a0
402 ; RV32I-NEXT: lui a1, 1048560
403 ; RV32I-NEXT: addi a1, a1, -1
404 ; RV32I-NEXT: sltu a1, a1, a2
405 ; RV32I-NEXT: seqz a0, a0
406 ; RV32I-NEXT: and a0, a0, a1
409 ; RV64I-LABEL: add_ugecmp_i64_i16:
411 ; RV64I-NEXT: lui a1, 1048568
412 ; RV64I-NEXT: add a0, a0, a1
413 ; RV64I-NEXT: lui a1, 1048560
414 ; RV64I-NEXT: addiw a1, a1, -1
415 ; RV64I-NEXT: sltu a0, a1, a0
418 ; RV32ZBB-LABEL: add_ugecmp_i64_i16:
420 ; RV32ZBB-NEXT: sext.h a2, a0
421 ; RV32ZBB-NEXT: xor a0, a2, a0
422 ; RV32ZBB-NEXT: srai a2, a2, 31
423 ; RV32ZBB-NEXT: xor a1, a2, a1
424 ; RV32ZBB-NEXT: or a0, a0, a1
425 ; RV32ZBB-NEXT: seqz a0, a0
428 ; RV64ZBB-LABEL: add_ugecmp_i64_i16:
430 ; RV64ZBB-NEXT: sext.h a1, a0
431 ; RV64ZBB-NEXT: xor a0, a1, a0
432 ; RV64ZBB-NEXT: seqz a0, a0
434 %tmp0 = add i64 %x, -32768 ; ~0U << (16-1)
435 %tmp1 = icmp uge i64 %tmp0, -65536 ; ~0U << 16
439 define i1 @add_ugecmp_i64_i8(i64 %x) nounwind {
440 ; RV32I-LABEL: add_ugecmp_i64_i8:
442 ; RV32I-NEXT: addi a2, a0, -128
443 ; RV32I-NEXT: sltu a0, a2, a0
444 ; RV32I-NEXT: add a0, a1, a0
445 ; RV32I-NEXT: seqz a0, a0
446 ; RV32I-NEXT: sltiu a1, a2, -256
447 ; RV32I-NEXT: xori a1, a1, 1
448 ; RV32I-NEXT: and a0, a0, a1
451 ; RV64-LABEL: add_ugecmp_i64_i8:
453 ; RV64-NEXT: addi a0, a0, -128
454 ; RV64-NEXT: sltiu a0, a0, -256
455 ; RV64-NEXT: xori a0, a0, 1
458 ; RV32ZBB-LABEL: add_ugecmp_i64_i8:
460 ; RV32ZBB-NEXT: sext.b a2, a0
461 ; RV32ZBB-NEXT: xor a0, a2, a0
462 ; RV32ZBB-NEXT: srai a2, a2, 31
463 ; RV32ZBB-NEXT: xor a1, a2, a1
464 ; RV32ZBB-NEXT: or a0, a0, a1
465 ; RV32ZBB-NEXT: seqz a0, a0
467 %tmp0 = add i64 %x, -128 ; ~0U << (8-1)
468 %tmp1 = icmp uge i64 %tmp0, -256 ; ~0U << 8
472 ; Slightly more canonical variant
473 define i1 @add_ugtcmp_i16_i8(i16 %x) nounwind {
474 ; RV32-LABEL: add_ugtcmp_i16_i8:
476 ; RV32-NEXT: addi a0, a0, -128
477 ; RV32-NEXT: slli a0, a0, 16
478 ; RV32-NEXT: srli a0, a0, 24
479 ; RV32-NEXT: sltiu a0, a0, 255
480 ; RV32-NEXT: xori a0, a0, 1
483 ; RV64-LABEL: add_ugtcmp_i16_i8:
485 ; RV64-NEXT: addi a0, a0, -128
486 ; RV64-NEXT: slli a0, a0, 48
487 ; RV64-NEXT: srli a0, a0, 56
488 ; RV64-NEXT: sltiu a0, a0, 255
489 ; RV64-NEXT: xori a0, a0, 1
491 %tmp0 = add i16 %x, -128 ; ~0U << (8-1)
492 %tmp1 = icmp ugt i16 %tmp0, -257 ; ~0U << 8 - 1
496 ; ---------------------------------------------------------------------------- ;
498 ; ---------------------------------------------------------------------------- ;
500 define i1 @add_ultcmp_i16_i8(i16 %x) nounwind {
501 ; RV32I-LABEL: add_ultcmp_i16_i8:
503 ; RV32I-NEXT: addi a0, a0, 128
504 ; RV32I-NEXT: slli a0, a0, 16
505 ; RV32I-NEXT: srli a0, a0, 16
506 ; RV32I-NEXT: sltiu a0, a0, 256
509 ; RV64I-LABEL: add_ultcmp_i16_i8:
511 ; RV64I-NEXT: addi a0, a0, 128
512 ; RV64I-NEXT: slli a0, a0, 48
513 ; RV64I-NEXT: srli a0, a0, 48
514 ; RV64I-NEXT: sltiu a0, a0, 256
517 ; RV32ZBB-LABEL: add_ultcmp_i16_i8:
519 ; RV32ZBB-NEXT: addi a0, a0, 128
520 ; RV32ZBB-NEXT: zext.h a0, a0
521 ; RV32ZBB-NEXT: sltiu a0, a0, 256
524 ; RV64ZBB-LABEL: add_ultcmp_i16_i8:
526 ; RV64ZBB-NEXT: addi a0, a0, 128
527 ; RV64ZBB-NEXT: zext.h a0, a0
528 ; RV64ZBB-NEXT: sltiu a0, a0, 256
530 %tmp0 = add i16 %x, 128 ; 1U << (8-1)
531 %tmp1 = icmp ult i16 %tmp0, 256 ; 1U << 8
535 define i1 @add_ultcmp_i32_i16(i32 %x) nounwind {
536 ; RV32I-LABEL: add_ultcmp_i32_i16:
538 ; RV32I-NEXT: lui a1, 8
539 ; RV32I-NEXT: add a0, a0, a1
540 ; RV32I-NEXT: srli a0, a0, 16
541 ; RV32I-NEXT: seqz a0, a0
544 ; RV64I-LABEL: add_ultcmp_i32_i16:
546 ; RV64I-NEXT: lui a1, 8
547 ; RV64I-NEXT: add a0, a0, a1
548 ; RV64I-NEXT: srliw a0, a0, 16
549 ; RV64I-NEXT: seqz a0, a0
552 ; RV32ZBB-LABEL: add_ultcmp_i32_i16:
554 ; RV32ZBB-NEXT: sext.h a1, a0
555 ; RV32ZBB-NEXT: xor a0, a1, a0
556 ; RV32ZBB-NEXT: seqz a0, a0
559 ; RV64ZBB-LABEL: add_ultcmp_i32_i16:
561 ; RV64ZBB-NEXT: sext.w a1, a0
562 ; RV64ZBB-NEXT: sext.h a0, a0
563 ; RV64ZBB-NEXT: xor a0, a0, a1
564 ; RV64ZBB-NEXT: seqz a0, a0
566 %tmp0 = add i32 %x, 32768 ; 1U << (16-1)
567 %tmp1 = icmp ult i32 %tmp0, 65536 ; 1U << 16
571 define i1 @add_ultcmp_i32_i8(i32 %x) nounwind {
572 ; RV32-LABEL: add_ultcmp_i32_i8:
574 ; RV32-NEXT: addi a0, a0, 128
575 ; RV32-NEXT: sltiu a0, a0, 256
578 ; RV64-LABEL: add_ultcmp_i32_i8:
580 ; RV64-NEXT: addiw a0, a0, 128
581 ; RV64-NEXT: sltiu a0, a0, 256
583 %tmp0 = add i32 %x, 128 ; 1U << (8-1)
584 %tmp1 = icmp ult i32 %tmp0, 256 ; 1U << 8
588 define i1 @add_ultcmp_i64_i32(i64 %x) nounwind {
589 ; RV32-LABEL: add_ultcmp_i64_i32:
591 ; RV32-NEXT: srai a0, a0, 31
592 ; RV32-NEXT: xor a0, a0, a1
593 ; RV32-NEXT: seqz a0, a0
596 ; RV64-LABEL: add_ultcmp_i64_i32:
598 ; RV64-NEXT: sext.w a1, a0
599 ; RV64-NEXT: xor a0, a1, a0
600 ; RV64-NEXT: seqz a0, a0
602 %tmp0 = add i64 %x, 2147483648 ; 1U << (32-1)
603 %tmp1 = icmp ult i64 %tmp0, 4294967296 ; 1U << 32
607 define i1 @add_ultcmp_i64_i16(i64 %x) nounwind {
608 ; RV32I-LABEL: add_ultcmp_i64_i16:
610 ; RV32I-NEXT: lui a2, 8
611 ; RV32I-NEXT: add a2, a0, a2
612 ; RV32I-NEXT: sltu a0, a2, a0
613 ; RV32I-NEXT: add a0, a1, a0
614 ; RV32I-NEXT: srli a2, a2, 16
615 ; RV32I-NEXT: or a0, a0, a2
616 ; RV32I-NEXT: seqz a0, a0
619 ; RV64I-LABEL: add_ultcmp_i64_i16:
621 ; RV64I-NEXT: lui a1, 8
622 ; RV64I-NEXT: add a0, a0, a1
623 ; RV64I-NEXT: srli a0, a0, 16
624 ; RV64I-NEXT: seqz a0, a0
627 ; RV32ZBB-LABEL: add_ultcmp_i64_i16:
629 ; RV32ZBB-NEXT: sext.h a2, a0
630 ; RV32ZBB-NEXT: xor a0, a2, a0
631 ; RV32ZBB-NEXT: srai a2, a2, 31
632 ; RV32ZBB-NEXT: xor a1, a2, a1
633 ; RV32ZBB-NEXT: or a0, a0, a1
634 ; RV32ZBB-NEXT: seqz a0, a0
637 ; RV64ZBB-LABEL: add_ultcmp_i64_i16:
639 ; RV64ZBB-NEXT: sext.h a1, a0
640 ; RV64ZBB-NEXT: xor a0, a1, a0
641 ; RV64ZBB-NEXT: seqz a0, a0
643 %tmp0 = add i64 %x, 32768 ; 1U << (16-1)
644 %tmp1 = icmp ult i64 %tmp0, 65536 ; 1U << 16
648 define i1 @add_ultcmp_i64_i8(i64 %x) nounwind {
649 ; RV32I-LABEL: add_ultcmp_i64_i8:
651 ; RV32I-NEXT: addi a2, a0, 128
652 ; RV32I-NEXT: sltu a0, a2, a0
653 ; RV32I-NEXT: add a0, a1, a0
654 ; RV32I-NEXT: seqz a0, a0
655 ; RV32I-NEXT: sltiu a1, a2, 256
656 ; RV32I-NEXT: and a0, a0, a1
659 ; RV64-LABEL: add_ultcmp_i64_i8:
661 ; RV64-NEXT: addi a0, a0, 128
662 ; RV64-NEXT: sltiu a0, a0, 256
665 ; RV32ZBB-LABEL: add_ultcmp_i64_i8:
667 ; RV32ZBB-NEXT: sext.b a2, a0
668 ; RV32ZBB-NEXT: xor a0, a2, a0
669 ; RV32ZBB-NEXT: srai a2, a2, 31
670 ; RV32ZBB-NEXT: xor a1, a2, a1
671 ; RV32ZBB-NEXT: or a0, a0, a1
672 ; RV32ZBB-NEXT: seqz a0, a0
674 %tmp0 = add i64 %x, 128 ; 1U << (8-1)
675 %tmp1 = icmp ult i64 %tmp0, 256 ; 1U << 8
679 ; Slightly more canonical variant
680 define i1 @add_ulecmp_i16_i8(i16 %x) nounwind {
681 ; RV32I-LABEL: add_ulecmp_i16_i8:
683 ; RV32I-NEXT: addi a0, a0, 128
684 ; RV32I-NEXT: slli a0, a0, 16
685 ; RV32I-NEXT: srli a0, a0, 16
686 ; RV32I-NEXT: sltiu a0, a0, 256
689 ; RV64I-LABEL: add_ulecmp_i16_i8:
691 ; RV64I-NEXT: addi a0, a0, 128
692 ; RV64I-NEXT: slli a0, a0, 48
693 ; RV64I-NEXT: srli a0, a0, 48
694 ; RV64I-NEXT: sltiu a0, a0, 256
697 ; RV32ZBB-LABEL: add_ulecmp_i16_i8:
699 ; RV32ZBB-NEXT: addi a0, a0, 128
700 ; RV32ZBB-NEXT: zext.h a0, a0
701 ; RV32ZBB-NEXT: sltiu a0, a0, 256
704 ; RV64ZBB-LABEL: add_ulecmp_i16_i8:
706 ; RV64ZBB-NEXT: addi a0, a0, 128
707 ; RV64ZBB-NEXT: zext.h a0, a0
708 ; RV64ZBB-NEXT: sltiu a0, a0, 256
710 %tmp0 = add i16 %x, 128 ; 1U << (8-1)
711 %tmp1 = icmp ule i16 %tmp0, 255 ; (1U << 8) - 1
716 ; ---------------------------------------------------------------------------- ;
718 ; Adding not a constant
719 define i1 @add_ultcmp_bad_i16_i8_add(i16 %x, i16 %y) nounwind {
720 ; RV32I-LABEL: add_ultcmp_bad_i16_i8_add:
722 ; RV32I-NEXT: add a0, a0, a1
723 ; RV32I-NEXT: slli a0, a0, 16
724 ; RV32I-NEXT: srli a0, a0, 16
725 ; RV32I-NEXT: sltiu a0, a0, 256
728 ; RV64I-LABEL: add_ultcmp_bad_i16_i8_add:
730 ; RV64I-NEXT: add a0, a0, a1
731 ; RV64I-NEXT: slli a0, a0, 48
732 ; RV64I-NEXT: srli a0, a0, 48
733 ; RV64I-NEXT: sltiu a0, a0, 256
736 ; RV32ZBB-LABEL: add_ultcmp_bad_i16_i8_add:
738 ; RV32ZBB-NEXT: add a0, a0, a1
739 ; RV32ZBB-NEXT: zext.h a0, a0
740 ; RV32ZBB-NEXT: sltiu a0, a0, 256
743 ; RV64ZBB-LABEL: add_ultcmp_bad_i16_i8_add:
745 ; RV64ZBB-NEXT: add a0, a0, a1
746 ; RV64ZBB-NEXT: zext.h a0, a0
747 ; RV64ZBB-NEXT: sltiu a0, a0, 256
749 %tmp0 = add i16 %x, %y
750 %tmp1 = icmp ult i16 %tmp0, 256 ; 1U << 8
754 ; Comparing not with a constant
755 define i1 @add_ultcmp_bad_i16_i8_cmp(i16 %x, i16 %y) nounwind {
756 ; RV32I-LABEL: add_ultcmp_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
766 ; RV64I-LABEL: add_ultcmp_bad_i16_i8_cmp:
768 ; RV64I-NEXT: lui a2, 16
769 ; RV64I-NEXT: addiw a2, a2, -1
770 ; RV64I-NEXT: and a1, a1, a2
771 ; RV64I-NEXT: addi a0, a0, 128
772 ; RV64I-NEXT: and a0, a0, a2
773 ; RV64I-NEXT: sltu a0, a0, a1
776 ; RV32ZBB-LABEL: add_ultcmp_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
784 ; RV64ZBB-LABEL: add_ultcmp_bad_i16_i8_cmp:
786 ; RV64ZBB-NEXT: zext.h a1, a1
787 ; RV64ZBB-NEXT: addi a0, a0, 128
788 ; RV64ZBB-NEXT: zext.h a0, a0
789 ; RV64ZBB-NEXT: sltu a0, a0, a1
791 %tmp0 = add i16 %x, 128 ; 1U << (8-1)
792 %tmp1 = icmp ult i16 %tmp0, %y
796 ; Second constant is not larger than the first one
797 define i1 @add_ultcmp_bad_i8_i16(i16 %x) nounwind {
798 ; RV32I-LABEL: add_ultcmp_bad_i8_i16:
800 ; RV32I-NEXT: addi a0, a0, 128
801 ; RV32I-NEXT: slli a0, a0, 16
802 ; RV32I-NEXT: srli a0, a0, 16
803 ; RV32I-NEXT: sltiu a0, a0, 128
806 ; RV64I-LABEL: add_ultcmp_bad_i8_i16:
808 ; RV64I-NEXT: addi a0, a0, 128
809 ; RV64I-NEXT: slli a0, a0, 48
810 ; RV64I-NEXT: srli a0, a0, 48
811 ; RV64I-NEXT: sltiu a0, a0, 128
814 ; RV32ZBB-LABEL: add_ultcmp_bad_i8_i16:
816 ; RV32ZBB-NEXT: addi a0, a0, 128
817 ; RV32ZBB-NEXT: zext.h a0, a0
818 ; RV32ZBB-NEXT: sltiu a0, a0, 128
821 ; RV64ZBB-LABEL: add_ultcmp_bad_i8_i16:
823 ; RV64ZBB-NEXT: addi a0, a0, 128
824 ; RV64ZBB-NEXT: zext.h a0, a0
825 ; RV64ZBB-NEXT: sltiu a0, a0, 128
827 %tmp0 = add i16 %x, 128 ; 1U << (8-1)
828 %tmp1 = icmp ult i16 %tmp0, 128 ; 1U << (8-1)
832 ; First constant is not power of two
833 define i1 @add_ultcmp_bad_i16_i8_c0notpoweroftwo(i16 %x) nounwind {
834 ; RV32I-LABEL: add_ultcmp_bad_i16_i8_c0notpoweroftwo:
836 ; RV32I-NEXT: addi a0, a0, 192
837 ; RV32I-NEXT: slli a0, a0, 16
838 ; RV32I-NEXT: srli a0, a0, 16
839 ; RV32I-NEXT: sltiu a0, a0, 256
842 ; RV64I-LABEL: add_ultcmp_bad_i16_i8_c0notpoweroftwo:
844 ; RV64I-NEXT: addi a0, a0, 192
845 ; RV64I-NEXT: slli a0, a0, 48
846 ; RV64I-NEXT: srli a0, a0, 48
847 ; RV64I-NEXT: sltiu a0, a0, 256
850 ; RV32ZBB-LABEL: add_ultcmp_bad_i16_i8_c0notpoweroftwo:
852 ; RV32ZBB-NEXT: addi a0, a0, 192
853 ; RV32ZBB-NEXT: zext.h a0, a0
854 ; RV32ZBB-NEXT: sltiu a0, a0, 256
857 ; RV64ZBB-LABEL: add_ultcmp_bad_i16_i8_c0notpoweroftwo:
859 ; RV64ZBB-NEXT: addi a0, a0, 192
860 ; RV64ZBB-NEXT: zext.h a0, a0
861 ; RV64ZBB-NEXT: sltiu a0, a0, 256
863 %tmp0 = add i16 %x, 192 ; (1U << (8-1)) + (1U << (8-1-1))
864 %tmp1 = icmp ult i16 %tmp0, 256 ; 1U << 8
868 ; Second constant is not power of two
869 define i1 @add_ultcmp_bad_i16_i8_c1notpoweroftwo(i16 %x) nounwind {
870 ; RV32I-LABEL: add_ultcmp_bad_i16_i8_c1notpoweroftwo:
872 ; RV32I-NEXT: addi a0, a0, 128
873 ; RV32I-NEXT: slli a0, a0, 16
874 ; RV32I-NEXT: srli a0, a0, 16
875 ; RV32I-NEXT: sltiu a0, a0, 768
878 ; RV64I-LABEL: add_ultcmp_bad_i16_i8_c1notpoweroftwo:
880 ; RV64I-NEXT: addi a0, a0, 128
881 ; RV64I-NEXT: slli a0, a0, 48
882 ; RV64I-NEXT: srli a0, a0, 48
883 ; RV64I-NEXT: sltiu a0, a0, 768
886 ; RV32ZBB-LABEL: add_ultcmp_bad_i16_i8_c1notpoweroftwo:
888 ; RV32ZBB-NEXT: addi a0, a0, 128
889 ; RV32ZBB-NEXT: zext.h a0, a0
890 ; RV32ZBB-NEXT: sltiu a0, a0, 768
893 ; RV64ZBB-LABEL: add_ultcmp_bad_i16_i8_c1notpoweroftwo:
895 ; RV64ZBB-NEXT: addi a0, a0, 128
896 ; RV64ZBB-NEXT: zext.h a0, a0
897 ; RV64ZBB-NEXT: sltiu a0, a0, 768
899 %tmp0 = add i16 %x, 128 ; 1U << (8-1)
900 %tmp1 = icmp ult i16 %tmp0, 768 ; (1U << 8)) + (1U << (8+1))
904 ; Magic check fails, 64 << 1 != 256
905 define i1 @add_ultcmp_bad_i16_i8_magic(i16 %x) nounwind {
906 ; RV32I-LABEL: add_ultcmp_bad_i16_i8_magic:
908 ; RV32I-NEXT: addi a0, a0, 64
909 ; RV32I-NEXT: slli a0, a0, 16
910 ; RV32I-NEXT: srli a0, a0, 16
911 ; RV32I-NEXT: sltiu a0, a0, 256
914 ; RV64I-LABEL: add_ultcmp_bad_i16_i8_magic:
916 ; RV64I-NEXT: addi a0, a0, 64
917 ; RV64I-NEXT: slli a0, a0, 48
918 ; RV64I-NEXT: srli a0, a0, 48
919 ; RV64I-NEXT: sltiu a0, a0, 256
922 ; RV32ZBB-LABEL: add_ultcmp_bad_i16_i8_magic:
924 ; RV32ZBB-NEXT: addi a0, a0, 64
925 ; RV32ZBB-NEXT: zext.h a0, a0
926 ; RV32ZBB-NEXT: sltiu a0, a0, 256
929 ; RV64ZBB-LABEL: add_ultcmp_bad_i16_i8_magic:
931 ; RV64ZBB-NEXT: addi a0, a0, 64
932 ; RV64ZBB-NEXT: zext.h a0, a0
933 ; RV64ZBB-NEXT: sltiu a0, a0, 256
935 %tmp0 = add i16 %x, 64 ; 1U << (8-1-1)
936 %tmp1 = icmp ult i16 %tmp0, 256 ; 1U << 8
940 ; Bad 'destination type'
941 define i1 @add_ultcmp_bad_i16_i4(i16 %x) nounwind {
942 ; RV32I-LABEL: add_ultcmp_bad_i16_i4:
944 ; RV32I-NEXT: addi a0, a0, 8
945 ; RV32I-NEXT: slli a0, a0, 16
946 ; RV32I-NEXT: srli a0, a0, 16
947 ; RV32I-NEXT: sltiu a0, a0, 16
950 ; RV64I-LABEL: add_ultcmp_bad_i16_i4:
952 ; RV64I-NEXT: addi a0, a0, 8
953 ; RV64I-NEXT: slli a0, a0, 48
954 ; RV64I-NEXT: srli a0, a0, 48
955 ; RV64I-NEXT: sltiu a0, a0, 16
958 ; RV32ZBB-LABEL: add_ultcmp_bad_i16_i4:
960 ; RV32ZBB-NEXT: addi a0, a0, 8
961 ; RV32ZBB-NEXT: zext.h a0, a0
962 ; RV32ZBB-NEXT: sltiu a0, a0, 16
965 ; RV64ZBB-LABEL: add_ultcmp_bad_i16_i4:
967 ; RV64ZBB-NEXT: addi a0, a0, 8
968 ; RV64ZBB-NEXT: zext.h a0, a0
969 ; RV64ZBB-NEXT: sltiu a0, a0, 16
971 %tmp0 = add i16 %x, 8 ; 1U << (4-1)
972 %tmp1 = icmp ult i16 %tmp0, 16 ; 1U << 4
977 define i1 @add_ultcmp_bad_i24_i8(i24 %x) nounwind {
978 ; RV32-LABEL: add_ultcmp_bad_i24_i8:
980 ; RV32-NEXT: addi a0, a0, 128
981 ; RV32-NEXT: slli a0, a0, 8
982 ; RV32-NEXT: srli a0, a0, 8
983 ; RV32-NEXT: sltiu a0, a0, 256
986 ; RV64-LABEL: add_ultcmp_bad_i24_i8:
988 ; RV64-NEXT: addi a0, a0, 128
989 ; RV64-NEXT: slli a0, a0, 40
990 ; RV64-NEXT: srli a0, a0, 40
991 ; RV64-NEXT: sltiu a0, a0, 256
993 %tmp0 = add i24 %x, 128 ; 1U << (8-1)
994 %tmp1 = icmp ult i24 %tmp0, 256 ; 1U << 8
998 define i1 @add_ulecmp_bad_i16_i8(i16 %x) nounwind {
999 ; CHECK-LABEL: add_ulecmp_bad_i16_i8:
1001 ; CHECK-NEXT: li a0, 1
1003 %tmp0 = add i16 %x, 128 ; 1U << (8-1)
1004 %tmp1 = icmp ule i16 %tmp0, -1 ; when we +1 it, it will wrap to 0