1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
3 ; RUN: | FileCheck %s -check-prefix=RV64I
4 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
5 ; RUN: | FileCheck %s -check-prefix=RV32I
7 ; These tests are each targeted at a particular RISC-V ALU instruction. Other
8 ; files in this folder exercise LLVM IR instructions that don't directly match a
9 ; RISC-V instruction. This file contains tests for the instructions common
10 ; between RV32I and RV64I as well as the *W instructions introduced in RV64I.
12 ; Register-immediate instructions
14 define i64 @addi(i64 %a) nounwind {
17 ; RV64I-NEXT: addi a0, a0, 1
22 ; RV32I-NEXT: addi a2, a0, 1
23 ; RV32I-NEXT: sltu a0, a2, a0
24 ; RV32I-NEXT: add a1, a1, a0
25 ; RV32I-NEXT: mv a0, a2
31 define i64 @slti(i64 %a) nounwind {
34 ; RV64I-NEXT: slti a0, a0, 2
39 ; RV32I-NEXT: beqz a1, .LBB1_2
40 ; RV32I-NEXT: # %bb.1:
41 ; RV32I-NEXT: slti a0, a1, 0
42 ; RV32I-NEXT: mv a1, zero
44 ; RV32I-NEXT: .LBB1_2:
45 ; RV32I-NEXT: sltiu a0, a0, 2
46 ; RV32I-NEXT: mv a1, zero
48 %1 = icmp slt i64 %a, 2
49 %2 = zext i1 %1 to i64
53 define i64 @sltiu(i64 %a) nounwind {
56 ; RV64I-NEXT: sltiu a0, a0, 3
61 ; RV32I-NEXT: beqz a1, .LBB2_2
62 ; RV32I-NEXT: # %bb.1:
63 ; RV32I-NEXT: mv a0, zero
64 ; RV32I-NEXT: mv a1, zero
66 ; RV32I-NEXT: .LBB2_2:
67 ; RV32I-NEXT: sltiu a0, a0, 3
68 ; RV32I-NEXT: mv a1, zero
70 %1 = icmp ult i64 %a, 3
71 %2 = zext i1 %1 to i64
75 define i64 @xori(i64 %a) nounwind {
78 ; RV64I-NEXT: xori a0, a0, 4
83 ; RV32I-NEXT: xori a0, a0, 4
89 define i64 @ori(i64 %a) nounwind {
92 ; RV64I-NEXT: ori a0, a0, 5
97 ; RV32I-NEXT: ori a0, a0, 5
103 define i64 @andi(i64 %a) nounwind {
106 ; RV64I-NEXT: andi a0, a0, 6
111 ; RV32I-NEXT: andi a0, a0, 6
112 ; RV32I-NEXT: mv a1, zero
118 define i64 @slli(i64 %a) nounwind {
121 ; RV64I-NEXT: slli a0, a0, 7
126 ; RV32I-NEXT: srli a2, a0, 25
127 ; RV32I-NEXT: slli a1, a1, 7
128 ; RV32I-NEXT: or a1, a1, a2
129 ; RV32I-NEXT: slli a0, a0, 7
135 define i64 @srli(i64 %a) nounwind {
138 ; RV64I-NEXT: srli a0, a0, 8
143 ; RV32I-NEXT: slli a2, a1, 24
144 ; RV32I-NEXT: srli a0, a0, 8
145 ; RV32I-NEXT: or a0, a0, a2
146 ; RV32I-NEXT: srli a1, a1, 8
152 define i64 @srai(i64 %a) nounwind {
155 ; RV64I-NEXT: srai a0, a0, 9
160 ; RV32I-NEXT: slli a2, a1, 23
161 ; RV32I-NEXT: srli a0, a0, 9
162 ; RV32I-NEXT: or a0, a0, a2
163 ; RV32I-NEXT: srai a1, a1, 9
169 ; Register-register instructions
171 define i64 @add(i64 %a, i64 %b) nounwind {
174 ; RV64I-NEXT: add a0, a0, a1
179 ; RV32I-NEXT: add a1, a1, a3
180 ; RV32I-NEXT: add a2, a0, a2
181 ; RV32I-NEXT: sltu a0, a2, a0
182 ; RV32I-NEXT: add a1, a1, a0
183 ; RV32I-NEXT: mv a0, a2
189 define i64 @sub(i64 %a, i64 %b) nounwind {
192 ; RV64I-NEXT: sub a0, a0, a1
197 ; RV32I-NEXT: sltu a4, a0, a2
198 ; RV32I-NEXT: sub a1, a1, a3
199 ; RV32I-NEXT: sub a1, a1, a4
200 ; RV32I-NEXT: sub a0, a0, a2
206 define i64 @sll(i64 %a, i64 %b) nounwind {
209 ; RV64I-NEXT: sll a0, a0, a1
214 ; RV32I-NEXT: addi a3, a2, -32
215 ; RV32I-NEXT: bltz a3, .LBB11_2
216 ; RV32I-NEXT: # %bb.1:
217 ; RV32I-NEXT: sll a1, a0, a3
218 ; RV32I-NEXT: mv a0, zero
220 ; RV32I-NEXT: .LBB11_2:
221 ; RV32I-NEXT: sll a1, a1, a2
222 ; RV32I-NEXT: addi a3, zero, 31
223 ; RV32I-NEXT: sub a3, a3, a2
224 ; RV32I-NEXT: srli a4, a0, 1
225 ; RV32I-NEXT: srl a3, a4, a3
226 ; RV32I-NEXT: or a1, a1, a3
227 ; RV32I-NEXT: sll a2, a0, a2
228 ; RV32I-NEXT: mv a0, a2
234 define i64 @slt(i64 %a, i64 %b) nounwind {
237 ; RV64I-NEXT: slt a0, a0, a1
242 ; RV32I-NEXT: beq a1, a3, .LBB12_2
243 ; RV32I-NEXT: # %bb.1:
244 ; RV32I-NEXT: slt a0, a1, a3
245 ; RV32I-NEXT: mv a1, zero
247 ; RV32I-NEXT: .LBB12_2:
248 ; RV32I-NEXT: sltu a0, a0, a2
249 ; RV32I-NEXT: mv a1, zero
251 %1 = icmp slt i64 %a, %b
252 %2 = zext i1 %1 to i64
256 define i64 @sltu(i64 %a, i64 %b) nounwind {
259 ; RV64I-NEXT: sltu a0, a0, a1
264 ; RV32I-NEXT: beq a1, a3, .LBB13_2
265 ; RV32I-NEXT: # %bb.1:
266 ; RV32I-NEXT: sltu a0, a1, a3
267 ; RV32I-NEXT: mv a1, zero
269 ; RV32I-NEXT: .LBB13_2:
270 ; RV32I-NEXT: sltu a0, a0, a2
271 ; RV32I-NEXT: mv a1, zero
273 %1 = icmp ult i64 %a, %b
274 %2 = zext i1 %1 to i64
278 define i64 @xor(i64 %a, i64 %b) nounwind {
281 ; RV64I-NEXT: xor a0, a0, a1
286 ; RV32I-NEXT: xor a0, a0, a2
287 ; RV32I-NEXT: xor a1, a1, a3
293 define i64 @srl(i64 %a, i64 %b) nounwind {
296 ; RV64I-NEXT: srl a0, a0, a1
301 ; RV32I-NEXT: addi a3, a2, -32
302 ; RV32I-NEXT: bltz a3, .LBB15_2
303 ; RV32I-NEXT: # %bb.1:
304 ; RV32I-NEXT: srl a0, a1, a3
305 ; RV32I-NEXT: mv a1, zero
307 ; RV32I-NEXT: .LBB15_2:
308 ; RV32I-NEXT: srl a0, a0, a2
309 ; RV32I-NEXT: addi a3, zero, 31
310 ; RV32I-NEXT: sub a3, a3, a2
311 ; RV32I-NEXT: slli a4, a1, 1
312 ; RV32I-NEXT: sll a3, a4, a3
313 ; RV32I-NEXT: or a0, a0, a3
314 ; RV32I-NEXT: srl a2, a1, a2
315 ; RV32I-NEXT: mv a1, a2
321 define i64 @sra(i64 %a, i64 %b) nounwind {
324 ; RV64I-NEXT: sra a0, a0, a1
329 ; RV32I-NEXT: addi a3, a2, -32
330 ; RV32I-NEXT: bltz a3, .LBB16_2
331 ; RV32I-NEXT: # %bb.1:
332 ; RV32I-NEXT: sra a0, a1, a3
333 ; RV32I-NEXT: srai a1, a1, 31
335 ; RV32I-NEXT: .LBB16_2:
336 ; RV32I-NEXT: srl a0, a0, a2
337 ; RV32I-NEXT: addi a3, zero, 31
338 ; RV32I-NEXT: sub a3, a3, a2
339 ; RV32I-NEXT: slli a4, a1, 1
340 ; RV32I-NEXT: sll a3, a4, a3
341 ; RV32I-NEXT: or a0, a0, a3
342 ; RV32I-NEXT: sra a1, a1, a2
348 define i64 @or(i64 %a, i64 %b) nounwind {
351 ; RV64I-NEXT: or a0, a0, a1
356 ; RV32I-NEXT: or a0, a0, a2
357 ; RV32I-NEXT: or a1, a1, a3
363 define i64 @and(i64 %a, i64 %b) nounwind {
366 ; RV64I-NEXT: and a0, a0, a1
371 ; RV32I-NEXT: and a0, a0, a2
372 ; RV32I-NEXT: and a1, a1, a3
378 ; RV64I-only instructions
380 define signext i32 @addiw(i32 signext %a) nounwind {
381 ; RV64I-LABEL: addiw:
383 ; RV64I-NEXT: addiw a0, a0, 123
386 ; RV32I-LABEL: addiw:
388 ; RV32I-NEXT: addi a0, a0, 123
394 define signext i32 @slliw(i32 signext %a) nounwind {
395 ; RV64I-LABEL: slliw:
397 ; RV64I-NEXT: slliw a0, a0, 17
400 ; RV32I-LABEL: slliw:
402 ; RV32I-NEXT: slli a0, a0, 17
408 define signext i32 @srliw(i32 %a) nounwind {
409 ; RV64I-LABEL: srliw:
411 ; RV64I-NEXT: srliw a0, a0, 8
414 ; RV32I-LABEL: srliw:
416 ; RV32I-NEXT: srli a0, a0, 8
422 define signext i32 @sraiw(i32 %a) nounwind {
423 ; RV64I-LABEL: sraiw:
425 ; RV64I-NEXT: sraiw a0, a0, 9
428 ; RV32I-LABEL: sraiw:
430 ; RV32I-NEXT: srai a0, a0, 9
436 define signext i32 @sextw(i32 zeroext %a) nounwind {
437 ; RV64I-LABEL: sextw:
439 ; RV64I-NEXT: sext.w a0, a0
442 ; RV32I-LABEL: sextw:
448 define signext i32 @addw(i32 signext %a, i32 signext %b) nounwind {
451 ; RV64I-NEXT: addw a0, a0, a1
456 ; RV32I-NEXT: add a0, a0, a1
462 define signext i32 @subw(i32 signext %a, i32 signext %b) nounwind {
465 ; RV64I-NEXT: subw a0, a0, a1
470 ; RV32I-NEXT: sub a0, a0, a1
476 define signext i32 @sllw(i32 signext %a, i32 zeroext %b) nounwind {
479 ; RV64I-NEXT: sllw a0, a0, a1
484 ; RV32I-NEXT: sll a0, a0, a1
490 define signext i32 @srlw(i32 signext %a, i32 zeroext %b) nounwind {
493 ; RV64I-NEXT: srlw a0, a0, a1
498 ; RV32I-NEXT: srl a0, a0, a1
504 define signext i32 @sraw(i64 %a, i32 zeroext %b) nounwind {
507 ; RV64I-NEXT: sraw a0, a0, a1
512 ; RV32I-NEXT: sra a0, a0, a2
514 %1 = trunc i64 %a to i32