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
6
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.
11
12; Register-immediate instructions
13
14define i64 @addi(i64 %a) nounwind {
15; RV64I-LABEL: addi:
16; RV64I:       # %bb.0:
17; RV64I-NEXT:    addi a0, a0, 1
18; RV64I-NEXT:    ret
19;
20; RV32I-LABEL: addi:
21; RV32I:       # %bb.0:
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
26; RV32I-NEXT:    ret
27  %1 = add i64 %a, 1
28  ret i64 %1
29}
30
31define i64 @slti(i64 %a) nounwind {
32; RV64I-LABEL: slti:
33; RV64I:       # %bb.0:
34; RV64I-NEXT:    slti a0, a0, 2
35; RV64I-NEXT:    ret
36;
37; RV32I-LABEL: slti:
38; RV32I:       # %bb.0:
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
43; RV32I-NEXT:    ret
44; RV32I-NEXT:  .LBB1_2:
45; RV32I-NEXT:    sltiu a0, a0, 2
46; RV32I-NEXT:    mv a1, zero
47; RV32I-NEXT:    ret
48  %1 = icmp slt i64 %a, 2
49  %2 = zext i1 %1 to i64
50  ret i64 %2
51}
52
53define i64 @sltiu(i64 %a) nounwind {
54; RV64I-LABEL: sltiu:
55; RV64I:       # %bb.0:
56; RV64I-NEXT:    sltiu a0, a0, 3
57; RV64I-NEXT:    ret
58;
59; RV32I-LABEL: sltiu:
60; RV32I:       # %bb.0:
61; RV32I-NEXT:    beqz a1, .LBB2_2
62; RV32I-NEXT:  # %bb.1:
63; RV32I-NEXT:    mv a0, zero
64; RV32I-NEXT:    mv a1, zero
65; RV32I-NEXT:    ret
66; RV32I-NEXT:  .LBB2_2:
67; RV32I-NEXT:    sltiu a0, a0, 3
68; RV32I-NEXT:    mv a1, zero
69; RV32I-NEXT:    ret
70  %1 = icmp ult i64 %a, 3
71  %2 = zext i1 %1 to i64
72  ret i64 %2
73}
74
75define i64 @xori(i64 %a) nounwind {
76; RV64I-LABEL: xori:
77; RV64I:       # %bb.0:
78; RV64I-NEXT:    xori a0, a0, 4
79; RV64I-NEXT:    ret
80;
81; RV32I-LABEL: xori:
82; RV32I:       # %bb.0:
83; RV32I-NEXT:    xori a0, a0, 4
84; RV32I-NEXT:    ret
85  %1 = xor i64 %a, 4
86  ret i64 %1
87}
88
89define i64 @ori(i64 %a) nounwind {
90; RV64I-LABEL: ori:
91; RV64I:       # %bb.0:
92; RV64I-NEXT:    ori a0, a0, 5
93; RV64I-NEXT:    ret
94;
95; RV32I-LABEL: ori:
96; RV32I:       # %bb.0:
97; RV32I-NEXT:    ori a0, a0, 5
98; RV32I-NEXT:    ret
99  %1 = or i64 %a, 5
100  ret i64 %1
101}
102
103define i64 @andi(i64 %a) nounwind {
104; RV64I-LABEL: andi:
105; RV64I:       # %bb.0:
106; RV64I-NEXT:    andi a0, a0, 6
107; RV64I-NEXT:    ret
108;
109; RV32I-LABEL: andi:
110; RV32I:       # %bb.0:
111; RV32I-NEXT:    andi a0, a0, 6
112; RV32I-NEXT:    mv a1, zero
113; RV32I-NEXT:    ret
114  %1 = and i64 %a, 6
115  ret i64 %1
116}
117
118define i64 @slli(i64 %a) nounwind {
119; RV64I-LABEL: slli:
120; RV64I:       # %bb.0:
121; RV64I-NEXT:    slli a0, a0, 7
122; RV64I-NEXT:    ret
123;
124; RV32I-LABEL: slli:
125; RV32I:       # %bb.0:
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
130; RV32I-NEXT:    ret
131  %1 = shl i64 %a, 7
132  ret i64 %1
133}
134
135define i64 @srli(i64 %a) nounwind {
136; RV64I-LABEL: srli:
137; RV64I:       # %bb.0:
138; RV64I-NEXT:    srli a0, a0, 8
139; RV64I-NEXT:    ret
140;
141; RV32I-LABEL: srli:
142; RV32I:       # %bb.0:
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
147; RV32I-NEXT:    ret
148  %1 = lshr i64 %a, 8
149  ret i64 %1
150}
151
152define i64 @srai(i64 %a) nounwind {
153; RV64I-LABEL: srai:
154; RV64I:       # %bb.0:
155; RV64I-NEXT:    srai a0, a0, 9
156; RV64I-NEXT:    ret
157;
158; RV32I-LABEL: srai:
159; RV32I:       # %bb.0:
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
164; RV32I-NEXT:    ret
165  %1 = ashr i64 %a, 9
166  ret i64 %1
167}
168
169; Register-register instructions
170
171define i64 @add(i64 %a, i64 %b) nounwind {
172; RV64I-LABEL: add:
173; RV64I:       # %bb.0:
174; RV64I-NEXT:    add a0, a0, a1
175; RV64I-NEXT:    ret
176;
177; RV32I-LABEL: add:
178; RV32I:       # %bb.0:
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
184; RV32I-NEXT:    ret
185  %1 = add i64 %a, %b
186  ret i64 %1
187}
188
189define i64 @sub(i64 %a, i64 %b) nounwind {
190; RV64I-LABEL: sub:
191; RV64I:       # %bb.0:
192; RV64I-NEXT:    sub a0, a0, a1
193; RV64I-NEXT:    ret
194;
195; RV32I-LABEL: sub:
196; RV32I:       # %bb.0:
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
201; RV32I-NEXT:    ret
202  %1 = sub i64 %a, %b
203  ret i64 %1
204}
205
206define i64 @sll(i64 %a, i64 %b) nounwind {
207; RV64I-LABEL: sll:
208; RV64I:       # %bb.0:
209; RV64I-NEXT:    sll a0, a0, a1
210; RV64I-NEXT:    ret
211;
212; RV32I-LABEL: sll:
213; RV32I:       # %bb.0:
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
219; RV32I-NEXT:    ret
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 a0, a0, a2
228; RV32I-NEXT:    ret
229  %1 = shl i64 %a, %b
230  ret i64 %1
231}
232
233define i64 @slt(i64 %a, i64 %b) nounwind {
234; RV64I-LABEL: slt:
235; RV64I:       # %bb.0:
236; RV64I-NEXT:    slt a0, a0, a1
237; RV64I-NEXT:    ret
238;
239; RV32I-LABEL: slt:
240; RV32I:       # %bb.0:
241; RV32I-NEXT:    beq a1, a3, .LBB12_2
242; RV32I-NEXT:  # %bb.1:
243; RV32I-NEXT:    slt a0, a1, a3
244; RV32I-NEXT:    mv a1, zero
245; RV32I-NEXT:    ret
246; RV32I-NEXT:  .LBB12_2:
247; RV32I-NEXT:    sltu a0, a0, a2
248; RV32I-NEXT:    mv a1, zero
249; RV32I-NEXT:    ret
250  %1 = icmp slt i64 %a, %b
251  %2 = zext i1 %1 to i64
252  ret i64 %2
253}
254
255define i64 @sltu(i64 %a, i64 %b) nounwind {
256; RV64I-LABEL: sltu:
257; RV64I:       # %bb.0:
258; RV64I-NEXT:    sltu a0, a0, a1
259; RV64I-NEXT:    ret
260;
261; RV32I-LABEL: sltu:
262; RV32I:       # %bb.0:
263; RV32I-NEXT:    beq a1, a3, .LBB13_2
264; RV32I-NEXT:  # %bb.1:
265; RV32I-NEXT:    sltu a0, a1, a3
266; RV32I-NEXT:    mv a1, zero
267; RV32I-NEXT:    ret
268; RV32I-NEXT:  .LBB13_2:
269; RV32I-NEXT:    sltu a0, a0, a2
270; RV32I-NEXT:    mv a1, zero
271; RV32I-NEXT:    ret
272  %1 = icmp ult i64 %a, %b
273  %2 = zext i1 %1 to i64
274  ret i64 %2
275}
276
277define i64 @xor(i64 %a, i64 %b) nounwind {
278; RV64I-LABEL: xor:
279; RV64I:       # %bb.0:
280; RV64I-NEXT:    xor a0, a0, a1
281; RV64I-NEXT:    ret
282;
283; RV32I-LABEL: xor:
284; RV32I:       # %bb.0:
285; RV32I-NEXT:    xor a0, a0, a2
286; RV32I-NEXT:    xor a1, a1, a3
287; RV32I-NEXT:    ret
288  %1 = xor i64 %a, %b
289  ret i64 %1
290}
291
292define i64 @srl(i64 %a, i64 %b) nounwind {
293; RV64I-LABEL: srl:
294; RV64I:       # %bb.0:
295; RV64I-NEXT:    srl a0, a0, a1
296; RV64I-NEXT:    ret
297;
298; RV32I-LABEL: srl:
299; RV32I:       # %bb.0:
300; RV32I-NEXT:    addi a3, a2, -32
301; RV32I-NEXT:    bltz a3, .LBB15_2
302; RV32I-NEXT:  # %bb.1:
303; RV32I-NEXT:    srl a0, a1, a3
304; RV32I-NEXT:    mv a1, zero
305; RV32I-NEXT:    ret
306; RV32I-NEXT:  .LBB15_2:
307; RV32I-NEXT:    srl a0, a0, a2
308; RV32I-NEXT:    addi a3, zero, 31
309; RV32I-NEXT:    sub a3, a3, a2
310; RV32I-NEXT:    slli a4, a1, 1
311; RV32I-NEXT:    sll a3, a4, a3
312; RV32I-NEXT:    or a0, a0, a3
313; RV32I-NEXT:    srl a1, a1, a2
314; RV32I-NEXT:    ret
315  %1 = lshr i64 %a, %b
316  ret i64 %1
317}
318
319define i64 @sra(i64 %a, i64 %b) nounwind {
320; RV64I-LABEL: sra:
321; RV64I:       # %bb.0:
322; RV64I-NEXT:    sra a0, a0, a1
323; RV64I-NEXT:    ret
324;
325; RV32I-LABEL: sra:
326; RV32I:       # %bb.0:
327; RV32I-NEXT:    addi a3, a2, -32
328; RV32I-NEXT:    bltz a3, .LBB16_2
329; RV32I-NEXT:  # %bb.1:
330; RV32I-NEXT:    sra a0, a1, a3
331; RV32I-NEXT:    srai a1, a1, 31
332; RV32I-NEXT:    ret
333; RV32I-NEXT:  .LBB16_2:
334; RV32I-NEXT:    srl a0, a0, a2
335; RV32I-NEXT:    addi a3, zero, 31
336; RV32I-NEXT:    sub a3, a3, a2
337; RV32I-NEXT:    slli a4, a1, 1
338; RV32I-NEXT:    sll a3, a4, a3
339; RV32I-NEXT:    or a0, a0, a3
340; RV32I-NEXT:    sra a1, a1, a2
341; RV32I-NEXT:    ret
342  %1 = ashr i64 %a, %b
343  ret i64 %1
344}
345
346define i64 @or(i64 %a, i64 %b) nounwind {
347; RV64I-LABEL: or:
348; RV64I:       # %bb.0:
349; RV64I-NEXT:    or a0, a0, a1
350; RV64I-NEXT:    ret
351;
352; RV32I-LABEL: or:
353; RV32I:       # %bb.0:
354; RV32I-NEXT:    or a0, a0, a2
355; RV32I-NEXT:    or a1, a1, a3
356; RV32I-NEXT:    ret
357  %1 = or i64 %a, %b
358  ret i64 %1
359}
360
361define i64 @and(i64 %a, i64 %b) nounwind {
362; RV64I-LABEL: and:
363; RV64I:       # %bb.0:
364; RV64I-NEXT:    and a0, a0, a1
365; RV64I-NEXT:    ret
366;
367; RV32I-LABEL: and:
368; RV32I:       # %bb.0:
369; RV32I-NEXT:    and a0, a0, a2
370; RV32I-NEXT:    and a1, a1, a3
371; RV32I-NEXT:    ret
372  %1 = and i64 %a, %b
373  ret i64 %1
374}
375
376; RV64I-only instructions
377
378define signext i32 @addiw(i32 signext %a) nounwind {
379; RV64I-LABEL: addiw:
380; RV64I:       # %bb.0:
381; RV64I-NEXT:    addiw a0, a0, 123
382; RV64I-NEXT:    ret
383;
384; RV32I-LABEL: addiw:
385; RV32I:       # %bb.0:
386; RV32I-NEXT:    addi a0, a0, 123
387; RV32I-NEXT:    ret
388  %1 = add i32 %a, 123
389  ret i32 %1
390}
391
392define signext i32 @slliw(i32 signext %a) nounwind {
393; RV64I-LABEL: slliw:
394; RV64I:       # %bb.0:
395; RV64I-NEXT:    slliw a0, a0, 17
396; RV64I-NEXT:    ret
397;
398; RV32I-LABEL: slliw:
399; RV32I:       # %bb.0:
400; RV32I-NEXT:    slli a0, a0, 17
401; RV32I-NEXT:    ret
402  %1 = shl i32 %a, 17
403  ret i32 %1
404}
405
406define signext i32 @srliw(i32 %a) nounwind {
407; RV64I-LABEL: srliw:
408; RV64I:       # %bb.0:
409; RV64I-NEXT:    srliw a0, a0, 8
410; RV64I-NEXT:    ret
411;
412; RV32I-LABEL: srliw:
413; RV32I:       # %bb.0:
414; RV32I-NEXT:    srli a0, a0, 8
415; RV32I-NEXT:    ret
416  %1 = lshr i32 %a, 8
417  ret i32 %1
418}
419
420define signext i32 @sraiw(i32 %a) nounwind {
421; RV64I-LABEL: sraiw:
422; RV64I:       # %bb.0:
423; RV64I-NEXT:    sraiw a0, a0, 9
424; RV64I-NEXT:    ret
425;
426; RV32I-LABEL: sraiw:
427; RV32I:       # %bb.0:
428; RV32I-NEXT:    srai a0, a0, 9
429; RV32I-NEXT:    ret
430  %1 = ashr i32 %a, 9
431  ret i32 %1
432}
433
434define signext i32 @sextw(i32 zeroext %a) nounwind {
435; RV64I-LABEL: sextw:
436; RV64I:       # %bb.0:
437; RV64I-NEXT:    sext.w a0, a0
438; RV64I-NEXT:    ret
439;
440; RV32I-LABEL: sextw:
441; RV32I:       # %bb.0:
442; RV32I-NEXT:    ret
443  ret i32 %a
444}
445
446define signext i32 @addw(i32 signext %a, i32 signext %b) nounwind {
447; RV64I-LABEL: addw:
448; RV64I:       # %bb.0:
449; RV64I-NEXT:    addw a0, a0, a1
450; RV64I-NEXT:    ret
451;
452; RV32I-LABEL: addw:
453; RV32I:       # %bb.0:
454; RV32I-NEXT:    add a0, a0, a1
455; RV32I-NEXT:    ret
456  %1 = add i32 %a, %b
457  ret i32 %1
458}
459
460define signext i32 @subw(i32 signext %a, i32 signext %b) nounwind {
461; RV64I-LABEL: subw:
462; RV64I:       # %bb.0:
463; RV64I-NEXT:    subw a0, a0, a1
464; RV64I-NEXT:    ret
465;
466; RV32I-LABEL: subw:
467; RV32I:       # %bb.0:
468; RV32I-NEXT:    sub a0, a0, a1
469; RV32I-NEXT:    ret
470  %1 = sub i32 %a, %b
471  ret i32 %1
472}
473
474define signext i32 @sllw(i32 signext %a, i32 zeroext %b) nounwind {
475; RV64I-LABEL: sllw:
476; RV64I:       # %bb.0:
477; RV64I-NEXT:    sllw a0, a0, a1
478; RV64I-NEXT:    ret
479;
480; RV32I-LABEL: sllw:
481; RV32I:       # %bb.0:
482; RV32I-NEXT:    sll a0, a0, a1
483; RV32I-NEXT:    ret
484  %1 = shl i32 %a, %b
485  ret i32 %1
486}
487
488define signext i32 @srlw(i32 signext %a, i32 zeroext %b) nounwind {
489; RV64I-LABEL: srlw:
490; RV64I:       # %bb.0:
491; RV64I-NEXT:    srlw a0, a0, a1
492; RV64I-NEXT:    ret
493;
494; RV32I-LABEL: srlw:
495; RV32I:       # %bb.0:
496; RV32I-NEXT:    srl a0, a0, a1
497; RV32I-NEXT:    ret
498  %1 = lshr i32 %a, %b
499  ret i32 %1
500}
501
502define signext i32 @sraw(i64 %a, i32 zeroext %b) nounwind {
503; RV64I-LABEL: sraw:
504; RV64I:       # %bb.0:
505; RV64I-NEXT:    sraw a0, a0, a1
506; RV64I-NEXT:    ret
507;
508; RV32I-LABEL: sraw:
509; RV32I:       # %bb.0:
510; RV32I-NEXT:    sra a0, a0, a2
511; RV32I-NEXT:    ret
512  %1 = trunc i64 %a to i32
513  %2 = ashr i32 %1, %b
514  ret i32 %2
515}
516