xref: /llvm-project/llvm/test/CodeGen/AVR/calling-conv/c/basic.ll (revision 7bdc80f35c325d148b1ddbdfce7dea8c6ba7af84)
1; RUN: llc -mtriple=avr < %s | FileCheck %s
2
3; CHECK-LABEL: ret_void_args_i8
4define void @ret_void_args_i8(i8 %a) {
5  ; CHECK: sts 4, r24
6  store volatile i8 %a, ptr inttoptr (i64 4 to ptr)
7  ret void
8}
9
10; CHECK-LABEL: ret_void_args_i8_i32
11define void @ret_void_args_i8_i32(i8 %a, i32 %b) {
12  ; CHECK:      sts     4, r24
13  store volatile i8 %a, ptr inttoptr (i64 4 to ptr)
14
15  ; CHECK-NEXT: sts     8, r23
16  ; CHECK-NEXT: sts     7, r22
17  ; CHECK-NEXT: sts     6, r21
18  ; CHECK-NEXT: sts     5, r20
19  store volatile i32 %b, ptr inttoptr (i64 5 to ptr)
20  ret void
21}
22
23; CHECK-LABEL: ret_void_args_i8_i8_i8_i8
24define void @ret_void_args_i8_i8_i8_i8(i8 %a, i8 %b, i8 %c, i8 %d) {
25  ; CHECK:      sts     4, r24
26  store volatile i8 %a, ptr inttoptr (i64 4 to ptr)
27  ; CHECK-NEXT: sts     5, r22
28  store volatile i8 %b, ptr inttoptr (i64 5 to ptr)
29  ; CHECK-NEXT: sts     6, r20
30  store volatile i8 %c, ptr inttoptr (i64 6 to ptr)
31  ; CHECK-NEXT: sts     7, r18
32  store volatile i8 %d, ptr inttoptr (i64 7 to ptr)
33  ret void
34}
35
36; CHECK-LABEL: ret_void_args_i32_16_i8
37define void @ret_void_args_i32_16_i8(i32 %a, i16 %b, i8 %c) {
38  ; CHECK:      sts     7, r25
39  ; CHECK-NEXT: sts     6, r24
40  ; CHECK-NEXT: sts     5, r23
41  ; CHECK-NEXT: sts     4, r22
42  store volatile i32 %a, ptr inttoptr (i64 4 to ptr)
43
44  ; CHECK-NEXT: sts     5, r21
45  ; CHECK-NEXT: sts     4, r20
46  store volatile i16 %b, ptr inttoptr (i64 4 to ptr)
47
48  ; CHECK-NEXT: sts     4, r18
49  store volatile i8 %c, ptr inttoptr (i64 4 to ptr)
50  ret void
51}
52
53; CHECK-LABEL: ret_void_args_i64
54define void @ret_void_args_i64(i64 %a) {
55  ; CHECK:      sts     11, r25
56  ; CHECK-NEXT: sts     10, r24
57  ; CHECK-NEXT: sts     9, r23
58  ; CHECK-NEXT: sts     8, r22
59  ; CHECK-NEXT: sts     7, r21
60  ; CHECK-NEXT: sts     6, r20
61  ; CHECK-NEXT: sts     5, r19
62  ; CHECK-NEXT: sts     4, r18
63  store volatile i64 %a, ptr inttoptr (i64 4 to ptr)
64  ret void
65}
66
67; CHECK-LABEL: ret_void_args_i64_i64
68define void @ret_void_args_i64_i64(i64 %a, i64 %b) {
69  ; CHECK-DAG:  sts     11, r25
70  ; CHECK-DAG: sts     10, r24
71  ; CHECK-DAG: sts     9, r23
72  ; CHECK-DAG: sts     8, r22
73  ; CHECK-DAG: sts     7, r21
74  ; CHECK-DAG: sts     6, r20
75  ; CHECK-DAG: sts     5, r19
76  ; CHECK-DAG: sts     4, r18
77  store volatile i64 %a, ptr inttoptr (i64 4 to ptr)
78
79  ; CHECK-DAG: sts     11, r17
80  ; CHECK-DAG: sts     10, r16
81  ; CHECK-DAG: sts     9, r15
82  ; CHECK-DAG: sts     8, r14
83  ; CHECK-DAG: sts     7, r13
84  ; CHECK-DAG: sts     6, r12
85  ; CHECK-DAG: sts     5, r11
86  ; CHECK-DAG: sts     4, r10
87  store volatile i64 %b, ptr inttoptr (i64 4 to ptr)
88  ret void
89}
90
91; This is exactly enough to hit the limit of what can be passed
92; completely in registers.
93; CHECK-LABEL: ret_void_args_i64_i64_i16
94define void @ret_void_args_i64_i64_i16(i64 %a, i64 %b, i16 %c) {
95  ; CHECK:      sts     5, r9
96  ; CHECK-NEXT: sts     4, r8
97  store volatile i16 %c, ptr inttoptr (i64 4 to ptr)
98  ret void
99}
100
101; NOTE: Both %a (i8) and %b (i8) cost two registers.
102define i8 @foo0(i8 %a, i8 %b) {
103; CHECK-LABEL: foo0:
104; CHECK:       ; %bb.0:
105; CHECK-NEXT:    sub r24, r22
106; CHECK-NEXT:    ret
107  %c = sub i8 %a, %b
108  ret i8 %c
109}
110
111; NOTE: Both %a (i16) and %b (i16) cost two registers.
112define i16 @foo1(i16 %a, i16 %b) {
113; CHECK-LABEL: foo1:
114; CHECK:       ; %bb.0:
115; CHECK-NEXT:    sub r24, r22
116; CHECK-NEXT:    sbc r25, r23
117; CHECK-NEXT:    ret
118  %c = sub i16 %a, %b
119  ret i16 %c
120}
121
122; NOTE: Both %a (i32) and %b (i32) cost four registers.
123define i32 @foo2(i32 %a, i32 %b) {
124; CHECK-LABEL: foo2:
125; CHECK:       ; %bb.0:
126; CHECK-NEXT:    sub r22, r18
127; CHECK-NEXT:    sbc r23, r19
128; CHECK-NEXT:    sbc r24, r20
129; CHECK-NEXT:    sbc r25, r21
130; CHECK-NEXT:    ret
131  %c = sub i32 %a, %b
132  ret i32 %c
133}
134
135; NOTE: Each argument costs four registers, and total 16 registers are used.
136define i32 @foo3(i32 %a, i32 %b, i32 %c, i32 %d) {
137; CHECK-LABEL: foo3:
138; CHECK:       ; %bb.0:
139; CHECK-NEXT:    sub r22, r10
140; CHECK-NEXT:    sbc r23, r11
141; CHECK-NEXT:    sbc r24, r12
142; CHECK-NEXT:    sbc r25, r13
143; CHECK-NEXT:    ret
144  %e = sub nsw i32 %a, %d
145  ret i32 %e
146}
147
148; NOTE: Each argument (except %e) cost four registers, and total 16 registers
149; NOTE: are used. Though there are still 2 registers are vacant, the %e has
150; NOTE: to be dropped to the stack.
151define i32 @foo4(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) {
152; CHECK-LABEL: foo4:
153; CHECK:       ; %bb.0:
154; CHECK-NEXT:    push r28
155; CHECK-NEXT:    push r29
156; CHECK-NEXT:    in r28, 61
157; CHECK-NEXT:    in r29, 62
158; CHECK-NEXT:    ldd r18, Y+5
159; CHECK-NEXT:    ldd r19, Y+6
160; CHECK-NEXT:    ldd r20, Y+7
161; CHECK-NEXT:    ldd r21, Y+8
162; CHECK-NEXT:    sub r22, r18
163; CHECK-NEXT:    sbc r23, r19
164; CHECK-NEXT:    sbc r24, r20
165; CHECK-NEXT:    sbc r25, r21
166; CHECK-NEXT:    pop r29
167; CHECK-NEXT:    pop r28
168; CHECK-NEXT:    ret
169  %f = sub nsw i32 %a, %e
170  ret i32 %f
171}
172