xref: /llvm-project/llvm/test/CodeGen/RISCV/GlobalISel/alu-roundtrip.ll (revision dde5546b79f784ab71cac325e0a0698c67c4dcde)
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
6
7; Extends to 32 bits exhaustively tested for add only.
8
9define i8 @add_i8(i8 %a, i8 %b) {
10; RV32IM-LABEL: add_i8:
11; RV32IM:       # %bb.0: # %entry
12; RV32IM-NEXT:    add a0, a0, a1
13; RV32IM-NEXT:    ret
14;
15; RV64IM-LABEL: add_i8:
16; RV64IM:       # %bb.0: # %entry
17; RV64IM-NEXT:    add a0, a0, a1
18; RV64IM-NEXT:    ret
19entry:
20  %0 = add i8 %a, %b
21  ret i8 %0
22}
23
24define 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
32; RV32IM-NEXT:    ret
33;
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:    addw a0, a0, a1
41; RV64IM-NEXT:    ret
42entry:
43  %0 = sext i8 %a to i32
44  %1 = sext i8 %b to i32
45  %2 = add i32 %0, %1
46  ret i32 %2
47}
48
49define 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
55; RV32IM-NEXT:    ret
56;
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:    addw a0, a0, a1
62; RV64IM-NEXT:    ret
63entry:
64  %0 = zext i8 %a to i32
65  %1 = zext i8 %b to i32
66  %2 = add i32 %0, %1
67  ret i32 %2
68}
69
70; TODO: Handle G_IMPLICIT_DEF, which is needed to have i8 -> i64 extends working
71; on RV32.
72
73define i32 @add_i32(i32 %a, i32 %b) {
74; RV32IM-LABEL: add_i32:
75; RV32IM:       # %bb.0: # %entry
76; RV32IM-NEXT:    add a0, a0, a1
77; RV32IM-NEXT:    ret
78;
79; RV64IM-LABEL: add_i32:
80; RV64IM:       # %bb.0: # %entry
81; RV64IM-NEXT:    addw a0, a0, a1
82; RV64IM-NEXT:    ret
83entry:
84  %0 = add i32 %a, %b
85  ret i32 %0
86}
87
88define i32 @addi_i32(i32 %a) {
89; RV32IM-LABEL: addi_i32:
90; RV32IM:       # %bb.0: # %entry
91; RV32IM-NEXT:    addi a0, a0, 1234
92; RV32IM-NEXT:    ret
93;
94; RV64IM-LABEL: addi_i32:
95; RV64IM:       # %bb.0: # %entry
96; RV64IM-NEXT:    addiw a0, a0, 1234
97; RV64IM-NEXT:    ret
98entry:
99  %0 = add i32 %a, 1234
100  ret i32 %0
101}
102
103define i32 @sub_i32(i32 %a, i32 %b) {
104; RV32IM-LABEL: sub_i32:
105; RV32IM:       # %bb.0: # %entry
106; RV32IM-NEXT:    sub a0, a0, a1
107; RV32IM-NEXT:    ret
108;
109; RV64IM-LABEL: sub_i32:
110; RV64IM:       # %bb.0: # %entry
111; RV64IM-NEXT:    subw a0, a0, a1
112; RV64IM-NEXT:    ret
113entry:
114  %0 = sub i32 %a, %b
115  ret i32 %0
116}
117
118define i32 @subi_i32(i32 %a) {
119; RV32IM-LABEL: subi_i32:
120; RV32IM:       # %bb.0: # %entry
121; RV32IM-NEXT:    addi a0, a0, -1234
122; RV32IM-NEXT:    ret
123;
124; RV64IM-LABEL: subi_i32:
125; RV64IM:       # %bb.0: # %entry
126; RV64IM-NEXT:    addiw a0, a0, -1234
127; RV64IM-NEXT:    ret
128entry:
129  %0 = sub i32 %a, 1234
130  ret i32 %0
131}
132
133define i32 @neg_i32(i32 %a) {
134; RV32IM-LABEL: neg_i32:
135; RV32IM:       # %bb.0: # %entry
136; RV32IM-NEXT:    neg a0, a0
137; RV32IM-NEXT:    ret
138;
139; RV64IM-LABEL: neg_i32:
140; RV64IM:       # %bb.0: # %entry
141; RV64IM-NEXT:    negw a0, a0
142; RV64IM-NEXT:    ret
143entry:
144  %0 = sub i32 0, %a
145  ret i32 %0
146}
147
148define i32 @sll_i32(i32 %a, i32 %b) {
149; RV32IM-LABEL: sll_i32:
150; RV32IM:       # %bb.0: # %entry
151; RV32IM-NEXT:    sll a0, a0, a1
152; RV32IM-NEXT:    ret
153;
154; RV64IM-LABEL: sll_i32:
155; RV64IM:       # %bb.0: # %entry
156; RV64IM-NEXT:    sllw a0, a0, a1
157; RV64IM-NEXT:    ret
158entry:
159  %0 = shl i32 %a, %b
160  ret i32 %0
161}
162
163define i32 @slli_i32(i32 %a) {
164; RV32IM-LABEL: slli_i32:
165; RV32IM:       # %bb.0: # %entry
166; RV32IM-NEXT:    slli a0, a0, 11
167; RV32IM-NEXT:    ret
168;
169; RV64IM-LABEL: slli_i32:
170; RV64IM:       # %bb.0: # %entry
171; RV64IM-NEXT:    slli a0, a0, 11
172; RV64IM-NEXT:    ret
173entry:
174  %0 = shl i32 %a, 11
175  ret i32 %0
176}
177
178define i32 @sra_i32(i32 %a, i32 %b) {
179; RV32IM-LABEL: sra_i32:
180; RV32IM:       # %bb.0: # %entry
181; RV32IM-NEXT:    sra a0, a0, a1
182; RV32IM-NEXT:    ret
183;
184; RV64IM-LABEL: sra_i32:
185; RV64IM:       # %bb.0: # %entry
186; RV64IM-NEXT:    sraw a0, a0, a1
187; RV64IM-NEXT:    ret
188entry:
189  %0 = ashr i32 %a, %b
190  ret i32 %0
191}
192
193define i32 @srai_i32(i32 %a) {
194; RV32IM-LABEL: srai_i32:
195; RV32IM:       # %bb.0: # %entry
196; RV32IM-NEXT:    srai a0, a0, 17
197; RV32IM-NEXT:    ret
198;
199; RV64IM-LABEL: srai_i32:
200; RV64IM:       # %bb.0: # %entry
201; RV64IM-NEXT:    sraiw a0, a0, 17
202; RV64IM-NEXT:    ret
203entry:
204  %0 = ashr i32 %a, 17
205  ret i32 %0
206}
207
208define i32 @srl_i32(i32 %a, i32 %b) {
209; RV32IM-LABEL: srl_i32:
210; RV32IM:       # %bb.0: # %entry
211; RV32IM-NEXT:    srl a0, a0, a1
212; RV32IM-NEXT:    ret
213;
214; RV64IM-LABEL: srl_i32:
215; RV64IM:       # %bb.0: # %entry
216; RV64IM-NEXT:    srlw a0, a0, a1
217; RV64IM-NEXT:    ret
218entry:
219  %0 = lshr i32 %a, %b
220  ret i32 %0
221}
222
223define i32 @srli_i32(i32 %a, i32 %b) {
224; RV32IM-LABEL: srli_i32:
225; RV32IM:       # %bb.0: # %entry
226; RV32IM-NEXT:    srli a0, a0, 23
227; RV32IM-NEXT:    ret
228;
229; RV64IM-LABEL: srli_i32:
230; RV64IM:       # %bb.0: # %entry
231; RV64IM-NEXT:    srliw a0, a0, 23
232; RV64IM-NEXT:    ret
233entry:
234  %0 = lshr i32 %a, 23
235  ret i32 %0
236}
237
238define i32 @and_i32(i32 %a, i32 %b) {
239; RV32IM-LABEL: and_i32:
240; RV32IM:       # %bb.0: # %entry
241; RV32IM-NEXT:    and a0, a0, a1
242; RV32IM-NEXT:    ret
243;
244; RV64IM-LABEL: and_i32:
245; RV64IM:       # %bb.0: # %entry
246; RV64IM-NEXT:    and a0, a0, a1
247; RV64IM-NEXT:    ret
248entry:
249  %0 = and i32 %a, %b
250  ret i32 %0
251}
252
253define i32 @andi_i32(i32 %a) {
254; RV32IM-LABEL: andi_i32:
255; RV32IM:       # %bb.0: # %entry
256; RV32IM-NEXT:    andi a0, a0, 1234
257; RV32IM-NEXT:    ret
258;
259; RV64IM-LABEL: andi_i32:
260; RV64IM:       # %bb.0: # %entry
261; RV64IM-NEXT:    andi a0, a0, 1234
262; RV64IM-NEXT:    ret
263entry:
264  %0 = and i32 %a, 1234
265  ret i32 %0
266}
267
268define i32 @or_i32(i32 %a, i32 %b) {
269; RV32IM-LABEL: or_i32:
270; RV32IM:       # %bb.0: # %entry
271; RV32IM-NEXT:    or a0, a0, a1
272; RV32IM-NEXT:    ret
273;
274; RV64IM-LABEL: or_i32:
275; RV64IM:       # %bb.0: # %entry
276; RV64IM-NEXT:    or a0, a0, a1
277; RV64IM-NEXT:    ret
278entry:
279  %0 = or i32 %a, %b
280  ret i32 %0
281}
282
283define i32 @ori_i32(i32 %a) {
284; RV32IM-LABEL: ori_i32:
285; RV32IM:       # %bb.0: # %entry
286; RV32IM-NEXT:    ori a0, a0, 1234
287; RV32IM-NEXT:    ret
288;
289; RV64IM-LABEL: ori_i32:
290; RV64IM:       # %bb.0: # %entry
291; RV64IM-NEXT:    ori a0, a0, 1234
292; RV64IM-NEXT:    ret
293entry:
294  %0 = or i32 %a, 1234
295  ret i32 %0
296}
297
298define i32 @xor_i32(i32 %a, i32 %b) {
299; RV32IM-LABEL: xor_i32:
300; RV32IM:       # %bb.0: # %entry
301; RV32IM-NEXT:    xor a0, a0, a1
302; RV32IM-NEXT:    ret
303;
304; RV64IM-LABEL: xor_i32:
305; RV64IM:       # %bb.0: # %entry
306; RV64IM-NEXT:    xor a0, a0, a1
307; RV64IM-NEXT:    ret
308entry:
309  %0 = xor i32 %a, %b
310  ret i32 %0
311}
312
313define i32 @xori_i32(i32 %a, i32 %b) {
314; RV32IM-LABEL: xori_i32:
315; RV32IM:       # %bb.0: # %entry
316; RV32IM-NEXT:    xori a0, a0, 1234
317; RV32IM-NEXT:    ret
318;
319; RV64IM-LABEL: xori_i32:
320; RV64IM:       # %bb.0: # %entry
321; RV64IM-NEXT:    xori a0, a0, 1234
322; RV64IM-NEXT:    ret
323entry:
324  %0 = xor i32 %a, 1234
325  ret i32 %0
326}
327
328define i32 @mul_i32(i32 %a, i32 %b) {
329; RV32IM-LABEL: mul_i32:
330; RV32IM:       # %bb.0: # %entry
331; RV32IM-NEXT:    mul a0, a0, a1
332; RV32IM-NEXT:    ret
333;
334; RV64IM-LABEL: mul_i32:
335; RV64IM:       # %bb.0: # %entry
336; RV64IM-NEXT:    mul a0, a0, a1
337; RV64IM-NEXT:    ret
338entry:
339  %0 = mul i32 %a, %b
340  ret i32 %0
341}
342
343define i32 @sdiv_i32(i32 %a, i32 %b) {
344; RV32IM-LABEL: sdiv_i32:
345; RV32IM:       # %bb.0: # %entry
346; RV32IM-NEXT:    div a0, a0, a1
347; RV32IM-NEXT:    ret
348;
349; RV64IM-LABEL: sdiv_i32:
350; RV64IM:       # %bb.0: # %entry
351; RV64IM-NEXT:    divw a0, a0, a1
352; RV64IM-NEXT:    ret
353entry:
354  %0 = sdiv i32 %a, %b
355  ret i32 %0
356}
357
358define i32 @srem_i32(i32 %a, i32 %b) {
359; RV32IM-LABEL: srem_i32:
360; RV32IM:       # %bb.0: # %entry
361; RV32IM-NEXT:    rem a0, a0, a1
362; RV32IM-NEXT:    ret
363;
364; RV64IM-LABEL: srem_i32:
365; RV64IM:       # %bb.0: # %entry
366; RV64IM-NEXT:    remw a0, a0, a1
367; RV64IM-NEXT:    ret
368entry:
369  %0 = srem i32 %a, %b
370  ret i32 %0
371}
372
373define i32 @udiv_i32(i32 %a, i32 %b) {
374; RV32IM-LABEL: udiv_i32:
375; RV32IM:       # %bb.0: # %entry
376; RV32IM-NEXT:    divu a0, a0, a1
377; RV32IM-NEXT:    ret
378;
379; RV64IM-LABEL: udiv_i32:
380; RV64IM:       # %bb.0: # %entry
381; RV64IM-NEXT:    divuw a0, a0, a1
382; RV64IM-NEXT:    ret
383entry:
384  %0 = udiv i32 %a, %b
385  ret i32 %0
386}
387
388define i32 @urem_i32(i32 %a, i32 %b) {
389; RV32IM-LABEL: urem_i32:
390; RV32IM:       # %bb.0: # %entry
391; RV32IM-NEXT:    remu a0, a0, a1
392; RV32IM-NEXT:    ret
393;
394; RV64IM-LABEL: urem_i32:
395; RV64IM:       # %bb.0: # %entry
396; RV64IM-NEXT:    remuw a0, a0, a1
397; RV64IM-NEXT:    ret
398entry:
399  %0 = urem i32 %a, %b
400  ret i32 %0
401}
402
403define 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
410; RV32IM-NEXT:    ret
411;
412; RV64IM-LABEL: add_i64:
413; RV64IM:       # %bb.0: # %entry
414; RV64IM-NEXT:    add a0, a0, a1
415; RV64IM-NEXT:    ret
416entry:
417  %0 = add i64 %a, %b
418  ret i64 %0
419}
420
421define 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
427; RV32IM-NEXT:    ret
428;
429; RV64IM-LABEL: addi_i64:
430; RV64IM:       # %bb.0: # %entry
431; RV64IM-NEXT:    addi a0, a0, 1234
432; RV64IM-NEXT:    ret
433entry:
434  %0 = add i64 %a, 1234
435  ret i64 %0
436}
437
438define 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
446; RV32IM-NEXT:    ret
447;
448; RV64IM-LABEL: sub_i64:
449; RV64IM:       # %bb.0: # %entry
450; RV64IM-NEXT:    sub a0, a0, a1
451; RV64IM-NEXT:    ret
452entry:
453  %0 = sub i64 %a, %b
454  ret i64 %0
455}
456
457define 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
466; RV32IM-NEXT:    ret
467;
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
473; RV64IM-NEXT:    ret
474entry:
475  %0 = sub i64 %a, 1234444
476  ret i64 %0
477}
478
479define 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
487; RV32IM-NEXT:    ret
488;
489; RV64IM-LABEL: neg_i64:
490; RV64IM:       # %bb.0: # %entry
491; RV64IM-NEXT:    neg a0, a0
492; RV64IM-NEXT:    ret
493entry:
494  %0 = sub i64 0, %a
495  ret i64 %0
496}
497
498; TODO: Handle G_SELECT, which is needed to have i64 shifts working on RV32.
499
500define 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
505; RV32IM-NEXT:    ret
506;
507; RV64IM-LABEL: and_i64:
508; RV64IM:       # %bb.0: # %entry
509; RV64IM-NEXT:    and a0, a0, a1
510; RV64IM-NEXT:    ret
511entry:
512  %0 = and i64 %a, %b
513  ret i64 %0
514}
515
516define 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
521; RV32IM-NEXT:    ret
522;
523; RV64IM-LABEL: andi_i64:
524; RV64IM:       # %bb.0: # %entry
525; RV64IM-NEXT:    andi a0, a0, 1234
526; RV64IM-NEXT:    ret
527entry:
528  %0 = and i64 %a, 1234
529  ret i64 %0
530}
531
532define 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
537; RV32IM-NEXT:    ret
538;
539; RV64IM-LABEL: or_i64:
540; RV64IM:       # %bb.0: # %entry
541; RV64IM-NEXT:    or a0, a0, a1
542; RV64IM-NEXT:    ret
543entry:
544  %0 = or i64 %a, %b
545  ret i64 %0
546}
547
548define i64 @ori_i64(i64 %a) {
549; RV32IM-LABEL: ori_i64:
550; RV32IM:       # %bb.0: # %entry
551; RV32IM-NEXT:    ori a0, a0, 1234
552; RV32IM-NEXT:    ret
553;
554; RV64IM-LABEL: ori_i64:
555; RV64IM:       # %bb.0: # %entry
556; RV64IM-NEXT:    ori a0, a0, 1234
557; RV64IM-NEXT:    ret
558entry:
559  %0 = or i64 %a, 1234
560  ret i64 %0
561}
562
563define 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
568; RV32IM-NEXT:    ret
569;
570; RV64IM-LABEL: xor_i64:
571; RV64IM:       # %bb.0: # %entry
572; RV64IM-NEXT:    xor a0, a0, a1
573; RV64IM-NEXT:    ret
574entry:
575  %0 = xor i64 %a, %b
576  ret i64 %0
577}
578
579define i64 @xori_i64(i64 %a) {
580; RV32IM-LABEL: xori_i64:
581; RV32IM:       # %bb.0: # %entry
582; RV32IM-NEXT:    xori a0, a0, 1234
583; RV32IM-NEXT:    ret
584;
585; RV64IM-LABEL: xori_i64:
586; RV64IM:       # %bb.0: # %entry
587; RV64IM-NEXT:    xori a0, a0, 1234
588; RV64IM-NEXT:    ret
589entry:
590  %0 = xor i64 %a, 1234
591  ret i64 %0
592}
593
594define 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
604; RV32IM-NEXT:    ret
605;
606; RV64IM-LABEL: mul_i64:
607; RV64IM:       # %bb.0: # %entry
608; RV64IM-NEXT:    mul a0, a0, a1
609; RV64IM-NEXT:    ret
610entry:
611  %0 = mul i64 %a, %b
612  ret i64 %0
613}
614
615; TODO: Handle G_SDIV, G_SREM, G_UDIV, G_UREM for i64 on RV32. Likely will be
616; dispatched to a libcall?
617