xref: /llvm-project/llvm/test/CodeGen/RISCV/alu64.ll (revision 55c6bda01ef5a166a69b43956775272d9d67bda5)
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 a0, a0, 1
23; RV32I-NEXT:    seqz a2, a0
24; RV32I-NEXT:    add a1, a1, a2
25; RV32I-NEXT:    ret
26  %1 = add i64 %a, 1
27  ret i64 %1
28}
29
30define i64 @slti(i64 %a) nounwind {
31; RV64I-LABEL: slti:
32; RV64I:       # %bb.0:
33; RV64I-NEXT:    slti a0, a0, 2
34; RV64I-NEXT:    ret
35;
36; RV32I-LABEL: slti:
37; RV32I:       # %bb.0:
38; RV32I-NEXT:    beqz a1, .LBB1_2
39; RV32I-NEXT:  # %bb.1:
40; RV32I-NEXT:    slti a0, a1, 0
41; RV32I-NEXT:    li a1, 0
42; RV32I-NEXT:    ret
43; RV32I-NEXT:  .LBB1_2:
44; RV32I-NEXT:    sltiu a0, a0, 2
45; RV32I-NEXT:    li a1, 0
46; RV32I-NEXT:    ret
47  %1 = icmp slt i64 %a, 2
48  %2 = zext i1 %1 to i64
49  ret i64 %2
50}
51
52define i64 @sltiu(i64 %a) nounwind {
53; RV64I-LABEL: sltiu:
54; RV64I:       # %bb.0:
55; RV64I-NEXT:    sltiu a0, a0, 3
56; RV64I-NEXT:    ret
57;
58; RV32I-LABEL: sltiu:
59; RV32I:       # %bb.0:
60; RV32I-NEXT:    sltiu a0, a0, 3
61; RV32I-NEXT:    seqz a1, a1
62; RV32I-NEXT:    and a0, a1, a0
63; RV32I-NEXT:    li a1, 0
64; RV32I-NEXT:    ret
65  %1 = icmp ult i64 %a, 3
66  %2 = zext i1 %1 to i64
67  ret i64 %2
68}
69
70define i64 @xori(i64 %a) nounwind {
71; RV64I-LABEL: xori:
72; RV64I:       # %bb.0:
73; RV64I-NEXT:    xori a0, a0, 4
74; RV64I-NEXT:    ret
75;
76; RV32I-LABEL: xori:
77; RV32I:       # %bb.0:
78; RV32I-NEXT:    xori a0, a0, 4
79; RV32I-NEXT:    ret
80  %1 = xor i64 %a, 4
81  ret i64 %1
82}
83
84define i64 @ori(i64 %a) nounwind {
85; RV64I-LABEL: ori:
86; RV64I:       # %bb.0:
87; RV64I-NEXT:    ori a0, a0, 5
88; RV64I-NEXT:    ret
89;
90; RV32I-LABEL: ori:
91; RV32I:       # %bb.0:
92; RV32I-NEXT:    ori a0, a0, 5
93; RV32I-NEXT:    ret
94  %1 = or i64 %a, 5
95  ret i64 %1
96}
97
98define i64 @andi(i64 %a) nounwind {
99; RV64I-LABEL: andi:
100; RV64I:       # %bb.0:
101; RV64I-NEXT:    andi a0, a0, 6
102; RV64I-NEXT:    ret
103;
104; RV32I-LABEL: andi:
105; RV32I:       # %bb.0:
106; RV32I-NEXT:    andi a0, a0, 6
107; RV32I-NEXT:    li a1, 0
108; RV32I-NEXT:    ret
109  %1 = and i64 %a, 6
110  ret i64 %1
111}
112
113define i64 @slli(i64 %a) nounwind {
114; RV64I-LABEL: slli:
115; RV64I:       # %bb.0:
116; RV64I-NEXT:    slli a0, a0, 7
117; RV64I-NEXT:    ret
118;
119; RV32I-LABEL: slli:
120; RV32I:       # %bb.0:
121; RV32I-NEXT:    srli a2, a0, 25
122; RV32I-NEXT:    slli a1, a1, 7
123; RV32I-NEXT:    or a1, a1, a2
124; RV32I-NEXT:    slli a0, a0, 7
125; RV32I-NEXT:    ret
126  %1 = shl i64 %a, 7
127  ret i64 %1
128}
129
130define i64 @srli(i64 %a) nounwind {
131; RV64I-LABEL: srli:
132; RV64I:       # %bb.0:
133; RV64I-NEXT:    srli a0, a0, 8
134; RV64I-NEXT:    ret
135;
136; RV32I-LABEL: srli:
137; RV32I:       # %bb.0:
138; RV32I-NEXT:    slli a2, a1, 24
139; RV32I-NEXT:    srli a0, a0, 8
140; RV32I-NEXT:    or a0, a0, a2
141; RV32I-NEXT:    srli a1, a1, 8
142; RV32I-NEXT:    ret
143  %1 = lshr i64 %a, 8
144  ret i64 %1
145}
146
147define i64 @srai(i64 %a) nounwind {
148; RV64I-LABEL: srai:
149; RV64I:       # %bb.0:
150; RV64I-NEXT:    srai a0, a0, 9
151; RV64I-NEXT:    ret
152;
153; RV32I-LABEL: srai:
154; RV32I:       # %bb.0:
155; RV32I-NEXT:    slli a2, a1, 23
156; RV32I-NEXT:    srli a0, a0, 9
157; RV32I-NEXT:    or a0, a0, a2
158; RV32I-NEXT:    srai a1, a1, 9
159; RV32I-NEXT:    ret
160  %1 = ashr i64 %a, 9
161  ret i64 %1
162}
163
164; Register-register instructions
165
166define i64 @add(i64 %a, i64 %b) nounwind {
167; RV64I-LABEL: add:
168; RV64I:       # %bb.0:
169; RV64I-NEXT:    add a0, a0, a1
170; RV64I-NEXT:    ret
171;
172; RV32I-LABEL: add:
173; RV32I:       # %bb.0:
174; RV32I-NEXT:    add a1, a1, a3
175; RV32I-NEXT:    add a2, a0, a2
176; RV32I-NEXT:    sltu a0, a2, a0
177; RV32I-NEXT:    add a1, a1, a0
178; RV32I-NEXT:    mv a0, a2
179; RV32I-NEXT:    ret
180  %1 = add i64 %a, %b
181  ret i64 %1
182}
183
184define i64 @sub(i64 %a, i64 %b) nounwind {
185; RV64I-LABEL: sub:
186; RV64I:       # %bb.0:
187; RV64I-NEXT:    sub a0, a0, a1
188; RV64I-NEXT:    ret
189;
190; RV32I-LABEL: sub:
191; RV32I:       # %bb.0:
192; RV32I-NEXT:    sltu a4, a0, a2
193; RV32I-NEXT:    sub a1, a1, a3
194; RV32I-NEXT:    sub a1, a1, a4
195; RV32I-NEXT:    sub a0, a0, a2
196; RV32I-NEXT:    ret
197  %1 = sub i64 %a, %b
198  ret i64 %1
199}
200
201define i64 @sll(i64 %a, i64 %b) nounwind {
202; RV64I-LABEL: sll:
203; RV64I:       # %bb.0:
204; RV64I-NEXT:    sll a0, a0, a1
205; RV64I-NEXT:    ret
206;
207; RV32I-LABEL: sll:
208; RV32I:       # %bb.0:
209; RV32I-NEXT:    addi a4, a2, -32
210; RV32I-NEXT:    sll a3, a0, a2
211; RV32I-NEXT:    bltz a4, .LBB11_2
212; RV32I-NEXT:  # %bb.1:
213; RV32I-NEXT:    mv a1, a3
214; RV32I-NEXT:    j .LBB11_3
215; RV32I-NEXT:  .LBB11_2:
216; RV32I-NEXT:    sll a1, a1, a2
217; RV32I-NEXT:    not a2, a2
218; RV32I-NEXT:    srli a0, a0, 1
219; RV32I-NEXT:    srl a0, a0, a2
220; RV32I-NEXT:    or a1, a1, a0
221; RV32I-NEXT:  .LBB11_3:
222; RV32I-NEXT:    srai a0, a4, 31
223; RV32I-NEXT:    and a0, a0, a3
224; RV32I-NEXT:    ret
225  %1 = shl i64 %a, %b
226  ret i64 %1
227}
228
229define i64 @slt(i64 %a, i64 %b) nounwind {
230; RV64I-LABEL: slt:
231; RV64I:       # %bb.0:
232; RV64I-NEXT:    slt a0, a0, a1
233; RV64I-NEXT:    ret
234;
235; RV32I-LABEL: slt:
236; RV32I:       # %bb.0:
237; RV32I-NEXT:    beq a1, a3, .LBB12_2
238; RV32I-NEXT:  # %bb.1:
239; RV32I-NEXT:    slt a0, a1, a3
240; RV32I-NEXT:    li a1, 0
241; RV32I-NEXT:    ret
242; RV32I-NEXT:  .LBB12_2:
243; RV32I-NEXT:    sltu a0, a0, a2
244; RV32I-NEXT:    li a1, 0
245; RV32I-NEXT:    ret
246  %1 = icmp slt i64 %a, %b
247  %2 = zext i1 %1 to i64
248  ret i64 %2
249}
250
251define i64 @sltu(i64 %a, i64 %b) nounwind {
252; RV64I-LABEL: sltu:
253; RV64I:       # %bb.0:
254; RV64I-NEXT:    sltu a0, a0, a1
255; RV64I-NEXT:    ret
256;
257; RV32I-LABEL: sltu:
258; RV32I:       # %bb.0:
259; RV32I-NEXT:    beq a1, a3, .LBB13_2
260; RV32I-NEXT:  # %bb.1:
261; RV32I-NEXT:    sltu a0, a1, a3
262; RV32I-NEXT:    li a1, 0
263; RV32I-NEXT:    ret
264; RV32I-NEXT:  .LBB13_2:
265; RV32I-NEXT:    sltu a0, a0, a2
266; RV32I-NEXT:    li a1, 0
267; RV32I-NEXT:    ret
268  %1 = icmp ult i64 %a, %b
269  %2 = zext i1 %1 to i64
270  ret i64 %2
271}
272
273define i64 @xor(i64 %a, i64 %b) nounwind {
274; RV64I-LABEL: xor:
275; RV64I:       # %bb.0:
276; RV64I-NEXT:    xor a0, a0, a1
277; RV64I-NEXT:    ret
278;
279; RV32I-LABEL: xor:
280; RV32I:       # %bb.0:
281; RV32I-NEXT:    xor a0, a0, a2
282; RV32I-NEXT:    xor a1, a1, a3
283; RV32I-NEXT:    ret
284  %1 = xor i64 %a, %b
285  ret i64 %1
286}
287
288define i64 @srl(i64 %a, i64 %b) nounwind {
289; RV64I-LABEL: srl:
290; RV64I:       # %bb.0:
291; RV64I-NEXT:    srl a0, a0, a1
292; RV64I-NEXT:    ret
293;
294; RV32I-LABEL: srl:
295; RV32I:       # %bb.0:
296; RV32I-NEXT:    addi a4, a2, -32
297; RV32I-NEXT:    srl a3, a1, a2
298; RV32I-NEXT:    bltz a4, .LBB15_2
299; RV32I-NEXT:  # %bb.1:
300; RV32I-NEXT:    mv a0, a3
301; RV32I-NEXT:    j .LBB15_3
302; RV32I-NEXT:  .LBB15_2:
303; RV32I-NEXT:    srl a0, a0, a2
304; RV32I-NEXT:    not a2, a2
305; RV32I-NEXT:    slli a1, a1, 1
306; RV32I-NEXT:    sll a1, a1, a2
307; RV32I-NEXT:    or a0, a0, a1
308; RV32I-NEXT:  .LBB15_3:
309; RV32I-NEXT:    srai a1, a4, 31
310; RV32I-NEXT:    and a1, a1, a3
311; RV32I-NEXT:    ret
312  %1 = lshr i64 %a, %b
313  ret i64 %1
314}
315
316define i64 @sra(i64 %a, i64 %b) nounwind {
317; RV64I-LABEL: sra:
318; RV64I:       # %bb.0:
319; RV64I-NEXT:    sra a0, a0, a1
320; RV64I-NEXT:    ret
321;
322; RV32I-LABEL: sra:
323; RV32I:       # %bb.0:
324; RV32I-NEXT:    mv a3, a1
325; RV32I-NEXT:    addi a4, a2, -32
326; RV32I-NEXT:    sra a1, a1, a2
327; RV32I-NEXT:    bltz a4, .LBB16_2
328; RV32I-NEXT:  # %bb.1:
329; RV32I-NEXT:    srai a3, a3, 31
330; RV32I-NEXT:    mv a0, a1
331; RV32I-NEXT:    mv a1, a3
332; RV32I-NEXT:    ret
333; RV32I-NEXT:  .LBB16_2:
334; RV32I-NEXT:    srl a0, a0, a2
335; RV32I-NEXT:    not a2, a2
336; RV32I-NEXT:    slli a3, a3, 1
337; RV32I-NEXT:    sll a2, a3, a2
338; RV32I-NEXT:    or a0, a0, a2
339; RV32I-NEXT:    ret
340  %1 = ashr i64 %a, %b
341  ret i64 %1
342}
343
344define i64 @or(i64 %a, i64 %b) nounwind {
345; RV64I-LABEL: or:
346; RV64I:       # %bb.0:
347; RV64I-NEXT:    or a0, a0, a1
348; RV64I-NEXT:    ret
349;
350; RV32I-LABEL: or:
351; RV32I:       # %bb.0:
352; RV32I-NEXT:    or a0, a0, a2
353; RV32I-NEXT:    or a1, a1, a3
354; RV32I-NEXT:    ret
355  %1 = or i64 %a, %b
356  ret i64 %1
357}
358
359define i64 @and(i64 %a, i64 %b) nounwind {
360; RV64I-LABEL: and:
361; RV64I:       # %bb.0:
362; RV64I-NEXT:    and a0, a0, a1
363; RV64I-NEXT:    ret
364;
365; RV32I-LABEL: and:
366; RV32I:       # %bb.0:
367; RV32I-NEXT:    and a0, a0, a2
368; RV32I-NEXT:    and a1, a1, a3
369; RV32I-NEXT:    ret
370  %1 = and i64 %a, %b
371  ret i64 %1
372}
373
374; RV64I-only instructions
375
376define signext i32 @addiw(i32 signext %a) nounwind {
377; RV64I-LABEL: addiw:
378; RV64I:       # %bb.0:
379; RV64I-NEXT:    addiw a0, a0, 123
380; RV64I-NEXT:    ret
381;
382; RV32I-LABEL: addiw:
383; RV32I:       # %bb.0:
384; RV32I-NEXT:    addi a0, a0, 123
385; RV32I-NEXT:    ret
386  %1 = add i32 %a, 123
387  ret i32 %1
388}
389
390define signext i32 @slliw(i32 signext %a) nounwind {
391; RV64I-LABEL: slliw:
392; RV64I:       # %bb.0:
393; RV64I-NEXT:    slliw a0, a0, 17
394; RV64I-NEXT:    ret
395;
396; RV32I-LABEL: slliw:
397; RV32I:       # %bb.0:
398; RV32I-NEXT:    slli a0, a0, 17
399; RV32I-NEXT:    ret
400  %1 = shl i32 %a, 17
401  ret i32 %1
402}
403
404define signext i32 @srliw(i32 %a) nounwind {
405; RV64I-LABEL: srliw:
406; RV64I:       # %bb.0:
407; RV64I-NEXT:    srliw a0, a0, 8
408; RV64I-NEXT:    ret
409;
410; RV32I-LABEL: srliw:
411; RV32I:       # %bb.0:
412; RV32I-NEXT:    srli a0, a0, 8
413; RV32I-NEXT:    ret
414  %1 = lshr i32 %a, 8
415  ret i32 %1
416}
417
418define signext i32 @sraiw(i32 %a) nounwind {
419; RV64I-LABEL: sraiw:
420; RV64I:       # %bb.0:
421; RV64I-NEXT:    sraiw a0, a0, 9
422; RV64I-NEXT:    ret
423;
424; RV32I-LABEL: sraiw:
425; RV32I:       # %bb.0:
426; RV32I-NEXT:    srai a0, a0, 9
427; RV32I-NEXT:    ret
428  %1 = ashr i32 %a, 9
429  ret i32 %1
430}
431
432define i64 @sraiw_i64(i64 %a) nounwind {
433; RV64I-LABEL: sraiw_i64:
434; RV64I:       # %bb.0:
435; RV64I-NEXT:    sraiw a0, a0, 9
436; RV64I-NEXT:    ret
437;
438; RV32I-LABEL: sraiw_i64:
439; RV32I:       # %bb.0:
440; RV32I-NEXT:    srai a2, a0, 9
441; RV32I-NEXT:    srai a1, a0, 31
442; RV32I-NEXT:    mv a0, a2
443; RV32I-NEXT:    ret
444  %1 = shl i64 %a, 32
445  %2 = ashr i64 %1, 41
446  ret i64 %2
447}
448
449define signext i32 @sextw(i32 zeroext %a) nounwind {
450; RV64I-LABEL: sextw:
451; RV64I:       # %bb.0:
452; RV64I-NEXT:    sext.w a0, a0
453; RV64I-NEXT:    ret
454;
455; RV32I-LABEL: sextw:
456; RV32I:       # %bb.0:
457; RV32I-NEXT:    ret
458  ret i32 %a
459}
460
461define signext i32 @addw(i32 signext %a, i32 signext %b) nounwind {
462; RV64I-LABEL: addw:
463; RV64I:       # %bb.0:
464; RV64I-NEXT:    addw a0, a0, a1
465; RV64I-NEXT:    ret
466;
467; RV32I-LABEL: addw:
468; RV32I:       # %bb.0:
469; RV32I-NEXT:    add a0, a0, a1
470; RV32I-NEXT:    ret
471  %1 = add i32 %a, %b
472  ret i32 %1
473}
474
475define signext i32 @subw(i32 signext %a, i32 signext %b) nounwind {
476; RV64I-LABEL: subw:
477; RV64I:       # %bb.0:
478; RV64I-NEXT:    subw a0, a0, a1
479; RV64I-NEXT:    ret
480;
481; RV32I-LABEL: subw:
482; RV32I:       # %bb.0:
483; RV32I-NEXT:    sub a0, a0, a1
484; RV32I-NEXT:    ret
485  %1 = sub i32 %a, %b
486  ret i32 %1
487}
488
489define signext i32 @sllw(i32 signext %a, i32 zeroext %b) nounwind {
490; RV64I-LABEL: sllw:
491; RV64I:       # %bb.0:
492; RV64I-NEXT:    sllw a0, a0, a1
493; RV64I-NEXT:    ret
494;
495; RV32I-LABEL: sllw:
496; RV32I:       # %bb.0:
497; RV32I-NEXT:    sll a0, a0, a1
498; RV32I-NEXT:    ret
499  %1 = shl i32 %a, %b
500  ret i32 %1
501}
502
503define signext i32 @srlw(i32 signext %a, i32 zeroext %b) nounwind {
504; RV64I-LABEL: srlw:
505; RV64I:       # %bb.0:
506; RV64I-NEXT:    srlw a0, a0, a1
507; RV64I-NEXT:    ret
508;
509; RV32I-LABEL: srlw:
510; RV32I:       # %bb.0:
511; RV32I-NEXT:    srl a0, a0, a1
512; RV32I-NEXT:    ret
513  %1 = lshr i32 %a, %b
514  ret i32 %1
515}
516
517define signext i32 @sraw(i64 %a, i32 zeroext %b) nounwind {
518; RV64I-LABEL: sraw:
519; RV64I:       # %bb.0:
520; RV64I-NEXT:    sraw a0, a0, a1
521; RV64I-NEXT:    ret
522;
523; RV32I-LABEL: sraw:
524; RV32I:       # %bb.0:
525; RV32I-NEXT:    sra a0, a0, a2
526; RV32I-NEXT:    ret
527  %1 = trunc i64 %a to i32
528  %2 = ashr i32 %1, %b
529  ret i32 %2
530}
531
532define i64 @add_hi_and_lo_negone(i64 %0) {
533; RV64I-LABEL: add_hi_and_lo_negone:
534; RV64I:       # %bb.0:
535; RV64I-NEXT:    addi a0, a0, -1
536; RV64I-NEXT:    ret
537;
538; RV32I-LABEL: add_hi_and_lo_negone:
539; RV32I:       # %bb.0:
540; RV32I-NEXT:    seqz a2, a0
541; RV32I-NEXT:    sub a1, a1, a2
542; RV32I-NEXT:    addi a0, a0, -1
543; RV32I-NEXT:    ret
544  %2 = add nsw i64 %0, -1
545  ret i64 %2
546}
547
548define i64 @add_hi_zero_lo_negone(i64 %0) {
549; RV64I-LABEL: add_hi_zero_lo_negone:
550; RV64I:       # %bb.0:
551; RV64I-NEXT:    li a1, -1
552; RV64I-NEXT:    srli a1, a1, 32
553; RV64I-NEXT:    add a0, a0, a1
554; RV64I-NEXT:    ret
555;
556; RV32I-LABEL: add_hi_zero_lo_negone:
557; RV32I:       # %bb.0:
558; RV32I-NEXT:    snez a2, a0
559; RV32I-NEXT:    add a1, a1, a2
560; RV32I-NEXT:    addi a0, a0, -1
561; RV32I-NEXT:    ret
562  %2 = add i64 %0, 4294967295
563  ret i64 %2
564}
565
566define i64 @add_lo_negone(i64 %0) {
567; RV64I-LABEL: add_lo_negone:
568; RV64I:       # %bb.0:
569; RV64I-NEXT:    li a1, -1
570; RV64I-NEXT:    slli a1, a1, 32
571; RV64I-NEXT:    addi a1, a1, -1
572; RV64I-NEXT:    add a0, a0, a1
573; RV64I-NEXT:    ret
574;
575; RV32I-LABEL: add_lo_negone:
576; RV32I:       # %bb.0:
577; RV32I-NEXT:    snez a2, a0
578; RV32I-NEXT:    add a1, a1, a2
579; RV32I-NEXT:    addi a1, a1, -2
580; RV32I-NEXT:    addi a0, a0, -1
581; RV32I-NEXT:    ret
582  %2 = add nsw i64 %0, -4294967297
583  ret i64 %2
584}
585
586define i64 @add_hi_one_lo_negone(i64 %0) {
587; RV64I-LABEL: add_hi_one_lo_negone:
588; RV64I:       # %bb.0:
589; RV64I-NEXT:    li a1, -1
590; RV64I-NEXT:    srli a1, a1, 31
591; RV64I-NEXT:    add a0, a0, a1
592; RV64I-NEXT:    ret
593;
594; RV32I-LABEL: add_hi_one_lo_negone:
595; RV32I:       # %bb.0:
596; RV32I-NEXT:    snez a2, a0
597; RV32I-NEXT:    add a1, a1, a2
598; RV32I-NEXT:    addi a1, a1, 1
599; RV32I-NEXT:    addi a0, a0, -1
600; RV32I-NEXT:    ret
601  %2 = add nsw i64 %0, 8589934591
602  ret i64 %2
603}
604