1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=riscv32 -mattr=+m -global-isel -verify-machineinstrs < %s \
3 ; RUN: -riscv-enable-copy-propagation=false | FileCheck %s --check-prefix=RV32IM
4 ; RUN: llc -mtriple=riscv64 -mattr=+m -global-isel -verify-machineinstrs < %s \
5 ; RUN: -riscv-enable-copy-propagation=false | FileCheck %s --check-prefix=RV64IM
7 ; Extends to 32 bits exhaustively tested for add only.
9 define i8 @add_i8(i8 %a, i8 %b) {
10 ; RV32IM-LABEL: add_i8:
11 ; RV32IM: # %bb.0: # %entry
12 ; RV32IM-NEXT: add a0, a0, a1
15 ; RV64IM-LABEL: add_i8:
16 ; RV64IM: # %bb.0: # %entry
17 ; RV64IM-NEXT: add a0, a0, a1
24 define i32 @add_i8_signext_i32(i8 %a, i8 %b) {
25 ; RV32IM-LABEL: add_i8_signext_i32:
26 ; RV32IM: # %bb.0: # %entry
27 ; RV32IM-NEXT: slli a0, a0, 24
28 ; RV32IM-NEXT: slli a1, a1, 24
29 ; RV32IM-NEXT: srai a0, a0, 24
30 ; RV32IM-NEXT: srai a1, a1, 24
31 ; RV32IM-NEXT: add a0, a0, a1
34 ; RV64IM-LABEL: add_i8_signext_i32:
35 ; RV64IM: # %bb.0: # %entry
36 ; RV64IM-NEXT: slli a0, a0, 56
37 ; RV64IM-NEXT: slli a1, a1, 56
38 ; RV64IM-NEXT: srai a0, a0, 56
39 ; RV64IM-NEXT: srai a1, a1, 56
40 ; RV64IM-NEXT: add a0, a0, a1
43 %0 = sext i8 %a to i32
44 %1 = sext i8 %b to i32
49 define i32 @add_i8_zeroext_i32(i8 %a, i8 %b) {
50 ; RV32IM-LABEL: add_i8_zeroext_i32:
51 ; RV32IM: # %bb.0: # %entry
52 ; RV32IM-NEXT: andi a0, a0, 255
53 ; RV32IM-NEXT: andi a1, a1, 255
54 ; RV32IM-NEXT: add a0, a0, a1
57 ; RV64IM-LABEL: add_i8_zeroext_i32:
58 ; RV64IM: # %bb.0: # %entry
59 ; RV64IM-NEXT: andi a0, a0, 255
60 ; RV64IM-NEXT: andi a1, a1, 255
61 ; RV64IM-NEXT: add a0, a0, a1
64 %0 = zext i8 %a to i32
65 %1 = zext i8 %b to i32
70 ; TODO: Handle G_IMPLICIT_DEF, which is needed to have i8 -> i64 extends working
73 define i32 @add_i32(i32 %a, i32 %b) {
74 ; RV32IM-LABEL: add_i32:
75 ; RV32IM: # %bb.0: # %entry
76 ; RV32IM-NEXT: add a0, a0, a1
79 ; RV64IM-LABEL: add_i32:
80 ; RV64IM: # %bb.0: # %entry
81 ; RV64IM-NEXT: add a0, a0, a1
88 define i32 @addi_i32(i32 %a) {
89 ; RV32IM-LABEL: addi_i32:
90 ; RV32IM: # %bb.0: # %entry
91 ; RV32IM-NEXT: addi a0, a0, 1234
94 ; RV64IM-LABEL: addi_i32:
95 ; RV64IM: # %bb.0: # %entry
96 ; RV64IM-NEXT: addi a0, a0, 1234
103 define i32 @sub_i32(i32 %a, i32 %b) {
104 ; RV32IM-LABEL: sub_i32:
105 ; RV32IM: # %bb.0: # %entry
106 ; RV32IM-NEXT: sub a0, a0, a1
109 ; RV64IM-LABEL: sub_i32:
110 ; RV64IM: # %bb.0: # %entry
111 ; RV64IM-NEXT: sub a0, a0, a1
118 define i32 @subi_i32(i32 %a) {
119 ; RV32IM-LABEL: subi_i32:
120 ; RV32IM: # %bb.0: # %entry
121 ; RV32IM-NEXT: addi a0, a0, -1234
124 ; RV64IM-LABEL: subi_i32:
125 ; RV64IM: # %bb.0: # %entry
126 ; RV64IM-NEXT: addi a0, a0, -1234
129 %0 = sub i32 %a, 1234
133 define i32 @neg_i32(i32 %a) {
134 ; RV32IM-LABEL: neg_i32:
135 ; RV32IM: # %bb.0: # %entry
136 ; RV32IM-NEXT: neg a0, a0
139 ; RV64IM-LABEL: neg_i32:
140 ; RV64IM: # %bb.0: # %entry
141 ; RV64IM-NEXT: neg a0, a0
148 define i32 @sll_i32(i32 %a, i32 %b) {
149 ; RV32IM-LABEL: sll_i32:
150 ; RV32IM: # %bb.0: # %entry
151 ; RV32IM-NEXT: sll a0, a0, a1
154 ; RV64IM-LABEL: sll_i32:
155 ; RV64IM: # %bb.0: # %entry
156 ; RV64IM-NEXT: sllw a0, a0, a1
163 define i32 @slli_i32(i32 %a) {
164 ; RV32IM-LABEL: slli_i32:
165 ; RV32IM: # %bb.0: # %entry
166 ; RV32IM-NEXT: slli a0, a0, 11
169 ; RV64IM-LABEL: slli_i32:
170 ; RV64IM: # %bb.0: # %entry
171 ; RV64IM-NEXT: slli a0, a0, 11
178 define i32 @sra_i32(i32 %a, i32 %b) {
179 ; RV32IM-LABEL: sra_i32:
180 ; RV32IM: # %bb.0: # %entry
181 ; RV32IM-NEXT: sra a0, a0, a1
184 ; RV64IM-LABEL: sra_i32:
185 ; RV64IM: # %bb.0: # %entry
186 ; RV64IM-NEXT: sraw a0, a0, a1
193 define i32 @srai_i32(i32 %a) {
194 ; RV32IM-LABEL: srai_i32:
195 ; RV32IM: # %bb.0: # %entry
196 ; RV32IM-NEXT: srai a0, a0, 17
199 ; RV64IM-LABEL: srai_i32:
200 ; RV64IM: # %bb.0: # %entry
201 ; RV64IM-NEXT: sraiw a0, a0, 17
208 define i32 @srl_i32(i32 %a, i32 %b) {
209 ; RV32IM-LABEL: srl_i32:
210 ; RV32IM: # %bb.0: # %entry
211 ; RV32IM-NEXT: srl a0, a0, a1
214 ; RV64IM-LABEL: srl_i32:
215 ; RV64IM: # %bb.0: # %entry
216 ; RV64IM-NEXT: srlw a0, a0, a1
223 define i32 @srli_i32(i32 %a, i32 %b) {
224 ; RV32IM-LABEL: srli_i32:
225 ; RV32IM: # %bb.0: # %entry
226 ; RV32IM-NEXT: srli a0, a0, 23
229 ; RV64IM-LABEL: srli_i32:
230 ; RV64IM: # %bb.0: # %entry
231 ; RV64IM-NEXT: srliw a0, a0, 23
238 define i32 @and_i32(i32 %a, i32 %b) {
239 ; RV32IM-LABEL: and_i32:
240 ; RV32IM: # %bb.0: # %entry
241 ; RV32IM-NEXT: and a0, a0, a1
244 ; RV64IM-LABEL: and_i32:
245 ; RV64IM: # %bb.0: # %entry
246 ; RV64IM-NEXT: and a0, a0, a1
253 define i32 @andi_i32(i32 %a) {
254 ; RV32IM-LABEL: andi_i32:
255 ; RV32IM: # %bb.0: # %entry
256 ; RV32IM-NEXT: andi a0, a0, 1234
259 ; RV64IM-LABEL: andi_i32:
260 ; RV64IM: # %bb.0: # %entry
261 ; RV64IM-NEXT: andi a0, a0, 1234
264 %0 = and i32 %a, 1234
268 define i32 @or_i32(i32 %a, i32 %b) {
269 ; RV32IM-LABEL: or_i32:
270 ; RV32IM: # %bb.0: # %entry
271 ; RV32IM-NEXT: or a0, a0, a1
274 ; RV64IM-LABEL: or_i32:
275 ; RV64IM: # %bb.0: # %entry
276 ; RV64IM-NEXT: or a0, a0, a1
283 define i32 @ori_i32(i32 %a) {
284 ; RV32IM-LABEL: ori_i32:
285 ; RV32IM: # %bb.0: # %entry
286 ; RV32IM-NEXT: ori a0, a0, 1234
289 ; RV64IM-LABEL: ori_i32:
290 ; RV64IM: # %bb.0: # %entry
291 ; RV64IM-NEXT: ori a0, a0, 1234
298 define i32 @xor_i32(i32 %a, i32 %b) {
299 ; RV32IM-LABEL: xor_i32:
300 ; RV32IM: # %bb.0: # %entry
301 ; RV32IM-NEXT: xor a0, a0, a1
304 ; RV64IM-LABEL: xor_i32:
305 ; RV64IM: # %bb.0: # %entry
306 ; RV64IM-NEXT: xor a0, a0, a1
313 define i32 @xori_i32(i32 %a, i32 %b) {
314 ; RV32IM-LABEL: xori_i32:
315 ; RV32IM: # %bb.0: # %entry
316 ; RV32IM-NEXT: xori a0, a0, 1234
319 ; RV64IM-LABEL: xori_i32:
320 ; RV64IM: # %bb.0: # %entry
321 ; RV64IM-NEXT: xori a0, a0, 1234
324 %0 = xor i32 %a, 1234
328 define i32 @mul_i32(i32 %a, i32 %b) {
329 ; RV32IM-LABEL: mul_i32:
330 ; RV32IM: # %bb.0: # %entry
331 ; RV32IM-NEXT: mul a0, a0, a1
334 ; RV64IM-LABEL: mul_i32:
335 ; RV64IM: # %bb.0: # %entry
336 ; RV64IM-NEXT: mul a0, a0, a1
343 define i32 @sdiv_i32(i32 %a, i32 %b) {
344 ; RV32IM-LABEL: sdiv_i32:
345 ; RV32IM: # %bb.0: # %entry
346 ; RV32IM-NEXT: div a0, a0, a1
349 ; RV64IM-LABEL: sdiv_i32:
350 ; RV64IM: # %bb.0: # %entry
351 ; RV64IM-NEXT: divw a0, a0, a1
358 define i32 @srem_i32(i32 %a, i32 %b) {
359 ; RV32IM-LABEL: srem_i32:
360 ; RV32IM: # %bb.0: # %entry
361 ; RV32IM-NEXT: rem a0, a0, a1
364 ; RV64IM-LABEL: srem_i32:
365 ; RV64IM: # %bb.0: # %entry
366 ; RV64IM-NEXT: remw a0, a0, a1
373 define i32 @udiv_i32(i32 %a, i32 %b) {
374 ; RV32IM-LABEL: udiv_i32:
375 ; RV32IM: # %bb.0: # %entry
376 ; RV32IM-NEXT: divu a0, a0, a1
379 ; RV64IM-LABEL: udiv_i32:
380 ; RV64IM: # %bb.0: # %entry
381 ; RV64IM-NEXT: divuw a0, a0, a1
388 define i32 @urem_i32(i32 %a, i32 %b) {
389 ; RV32IM-LABEL: urem_i32:
390 ; RV32IM: # %bb.0: # %entry
391 ; RV32IM-NEXT: remu a0, a0, a1
394 ; RV64IM-LABEL: urem_i32:
395 ; RV64IM: # %bb.0: # %entry
396 ; RV64IM-NEXT: remuw a0, a0, a1
403 define i64 @add_i64(i64 %a, i64 %b) {
404 ; RV32IM-LABEL: add_i64:
405 ; RV32IM: # %bb.0: # %entry
406 ; RV32IM-NEXT: add a0, a0, a2
407 ; RV32IM-NEXT: sltu a2, a0, a2
408 ; RV32IM-NEXT: add a1, a1, a3
409 ; RV32IM-NEXT: add a1, a1, a2
412 ; RV64IM-LABEL: add_i64:
413 ; RV64IM: # %bb.0: # %entry
414 ; RV64IM-NEXT: add a0, a0, a1
421 define i64 @addi_i64(i64 %a) {
422 ; RV32IM-LABEL: addi_i64:
423 ; RV32IM: # %bb.0: # %entry
424 ; RV32IM-NEXT: addi a0, a0, 1234
425 ; RV32IM-NEXT: sltiu a2, a0, 1234
426 ; RV32IM-NEXT: add a1, a1, a2
429 ; RV64IM-LABEL: addi_i64:
430 ; RV64IM: # %bb.0: # %entry
431 ; RV64IM-NEXT: addi a0, a0, 1234
434 %0 = add i64 %a, 1234
438 define i64 @sub_i64(i64 %a, i64 %b) {
439 ; RV32IM-LABEL: sub_i64:
440 ; RV32IM: # %bb.0: # %entry
441 ; RV32IM-NEXT: sub a4, a0, a2
442 ; RV32IM-NEXT: sltu a0, a0, a2
443 ; RV32IM-NEXT: sub a1, a1, a3
444 ; RV32IM-NEXT: sub a1, a1, a0
445 ; RV32IM-NEXT: mv a0, a4
448 ; RV64IM-LABEL: sub_i64:
449 ; RV64IM: # %bb.0: # %entry
450 ; RV64IM-NEXT: sub a0, a0, a1
457 define i64 @subi_i64(i64 %a) {
458 ; RV32IM-LABEL: subi_i64:
459 ; RV32IM: # %bb.0: # %entry
460 ; RV32IM-NEXT: lui a2, 1048275
461 ; RV32IM-NEXT: addi a2, a2, -1548
462 ; RV32IM-NEXT: add a0, a0, a2
463 ; RV32IM-NEXT: sltu a2, a0, a2
464 ; RV32IM-NEXT: addi a1, a1, -1
465 ; RV32IM-NEXT: add a1, a1, a2
468 ; RV64IM-LABEL: subi_i64:
469 ; RV64IM: # %bb.0: # %entry
470 ; RV64IM-NEXT: lui a1, 1048275
471 ; RV64IM-NEXT: addiw a1, a1, -1548
472 ; RV64IM-NEXT: add a0, a0, a1
475 %0 = sub i64 %a, 1234444
479 define i64 @neg_i64(i64 %a) {
480 ; RV32IM-LABEL: neg_i64:
481 ; RV32IM: # %bb.0: # %entry
482 ; RV32IM-NEXT: neg a2, a0
483 ; RV32IM-NEXT: snez a0, a0
484 ; RV32IM-NEXT: neg a1, a1
485 ; RV32IM-NEXT: sub a1, a1, a0
486 ; RV32IM-NEXT: mv a0, a2
489 ; RV64IM-LABEL: neg_i64:
490 ; RV64IM: # %bb.0: # %entry
491 ; RV64IM-NEXT: neg a0, a0
498 ; TODO: Handle G_SELECT, which is needed to have i64 shifts working on RV32.
500 define i64 @and_i64(i64 %a, i64 %b) {
501 ; RV32IM-LABEL: and_i64:
502 ; RV32IM: # %bb.0: # %entry
503 ; RV32IM-NEXT: and a0, a0, a2
504 ; RV32IM-NEXT: and a1, a1, a3
507 ; RV64IM-LABEL: and_i64:
508 ; RV64IM: # %bb.0: # %entry
509 ; RV64IM-NEXT: and a0, a0, a1
516 define i64 @andi_i64(i64 %a) {
517 ; RV32IM-LABEL: andi_i64:
518 ; RV32IM: # %bb.0: # %entry
519 ; RV32IM-NEXT: andi a0, a0, 1234
520 ; RV32IM-NEXT: li a1, 0
523 ; RV64IM-LABEL: andi_i64:
524 ; RV64IM: # %bb.0: # %entry
525 ; RV64IM-NEXT: andi a0, a0, 1234
528 %0 = and i64 %a, 1234
532 define i64 @or_i64(i64 %a, i64 %b) {
533 ; RV32IM-LABEL: or_i64:
534 ; RV32IM: # %bb.0: # %entry
535 ; RV32IM-NEXT: or a0, a0, a2
536 ; RV32IM-NEXT: or a1, a1, a3
539 ; RV64IM-LABEL: or_i64:
540 ; RV64IM: # %bb.0: # %entry
541 ; RV64IM-NEXT: or a0, a0, a1
548 define i64 @ori_i64(i64 %a) {
549 ; RV32IM-LABEL: ori_i64:
550 ; RV32IM: # %bb.0: # %entry
551 ; RV32IM-NEXT: ori a0, a0, 1234
554 ; RV64IM-LABEL: ori_i64:
555 ; RV64IM: # %bb.0: # %entry
556 ; RV64IM-NEXT: ori a0, a0, 1234
563 define i64 @xor_i64(i64 %a, i64 %b) {
564 ; RV32IM-LABEL: xor_i64:
565 ; RV32IM: # %bb.0: # %entry
566 ; RV32IM-NEXT: xor a0, a0, a2
567 ; RV32IM-NEXT: xor a1, a1, a3
570 ; RV64IM-LABEL: xor_i64:
571 ; RV64IM: # %bb.0: # %entry
572 ; RV64IM-NEXT: xor a0, a0, a1
579 define i64 @xori_i64(i64 %a) {
580 ; RV32IM-LABEL: xori_i64:
581 ; RV32IM: # %bb.0: # %entry
582 ; RV32IM-NEXT: xori a0, a0, 1234
585 ; RV64IM-LABEL: xori_i64:
586 ; RV64IM: # %bb.0: # %entry
587 ; RV64IM-NEXT: xori a0, a0, 1234
590 %0 = xor i64 %a, 1234
594 define i64 @mul_i64(i64 %a, i64 %b) {
595 ; RV32IM-LABEL: mul_i64:
596 ; RV32IM: # %bb.0: # %entry
597 ; RV32IM-NEXT: mul a4, a0, a2
598 ; RV32IM-NEXT: mul a1, a1, a2
599 ; RV32IM-NEXT: mul a3, a0, a3
600 ; RV32IM-NEXT: mulhu a0, a0, a2
601 ; RV32IM-NEXT: add a1, a1, a3
602 ; RV32IM-NEXT: add a1, a1, a0
603 ; RV32IM-NEXT: mv a0, a4
606 ; RV64IM-LABEL: mul_i64:
607 ; RV64IM: # %bb.0: # %entry
608 ; RV64IM-NEXT: mul a0, a0, a1
615 ; TODO: Handle G_SDIV, G_SREM, G_UDIV, G_UREM for i64 on RV32. Likely will be
616 ; dispatched to a libcall?