xref: /llvm-project/llvm/test/CodeGen/AVR/call.ll (revision 7bdc80f35c325d148b1ddbdfce7dea8c6ba7af84)
1; RUN: llc < %s -mtriple=avr -mcpu=avr6 | FileCheck %s --check-prefixes=CHECK,AVR6
2; RUN: llc < %s -mtriple=avr -mcpu=avr2 | FileCheck %s --check-prefixes=CHECK,AVR2
3
4; TODO: test returning byval structs
5
6declare i8 @foo8_1(i8)
7declare i8 @foo8_2(i8, i8, i8)
8declare i8 @foo8_3(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8)
9
10declare i16 @foo16_1(i16, i16)
11declare i16 @foo16_2(i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16)
12
13declare i32 @foo32_1(i32, i32)
14declare i32 @foo32_2(i32, i32, i32, i32, i32)
15
16declare i64 @foo64_1(i64)
17declare i64 @foo64_2(i64, i64, i64)
18
19define i8 @calli8_reg() {
20; CHECK-LABEL: calli8_reg:
21; CHECK: ldi r24, 12
22; AVR6:  call foo8_1
23; AVR2:  rcall foo8_1
24; CHECK: ldi r24, 12
25; CHECK: ldi r22, 13
26; CHECK: ldi r20, 14
27; AVR6:  call foo8_2
28; AVR2:  rcall foo8_2
29    %result1 = call i8 @foo8_1(i8 12)
30    %result2 = call i8 @foo8_2(i8 12, i8 13, i8 14)
31    ret i8 %result2
32}
33
34define i8 @calli8_stack() {
35; CHECK-LABEL: calli8_stack:
36; CHECK: ldi [[REG1:r[0-9]+]], 10
37; CHECK: ldi [[REG2:r[0-9]+]], 11
38; CHECK: std Z+2, [[REG2]]
39; CHECK: std Z+1, [[REG1]]
40; AVR6:  call foo8_3
41; AVR2:  rcall foo8_3
42    %result1 = call i8 @foo8_3(i8 1, i8 2, i8 3, i8 4, i8 5, i8 6, i8 7, i8 8, i8 9, i8 10, i8 11)
43    ret i8 %result1
44}
45
46define i16 @calli16_reg() {
47; CHECK-LABEL: calli16_reg:
48; CHECK: ldi r24, 1
49; CHECK: ldi r25, 2
50; CHECK: ldi r22, 2
51; CHECK: ldi r23, 2
52; AVR6:  call foo16_1
53; AVR2:  rcall foo16_1
54    %result1 = call i16 @foo16_1(i16 513, i16 514)
55    ret i16 %result1
56}
57
58define i16 @calli16_stack() {
59; CHECK-LABEL: calli16_stack:
60; CHECK: ldi [[REG1:r[0-9]+]], 10
61; CHECK: ldi [[REG2:r[0-9]+]], 2
62; CHECK: std Z+4, [[REG2]]
63; CHECK: std Z+3, [[REG1]]
64; CHECK: ldi [[REG1:r[0-9]+]], 9
65; CHECK: ldi [[REG2:r[0-9]+]], 2
66; CHECK: std Z+2, [[REG2]]
67; CHECK: std Z+1, [[REG1]]
68; AVR6:  call foo16_2
69; AVR2:  rcall foo16_2
70    %result1 = call i16 @foo16_2(i16 512, i16 513, i16 514, i16 515, i16 516, i16 517, i16 518, i16 519, i16 520, i16 521, i16 522)
71    ret i16 %result1
72}
73
74define i32 @calli32_reg() {
75; CHECK-LABEL: calli32_reg:
76; CHECK: ldi r22, 64
77; CHECK: ldi r23, 66
78; CHECK: ldi r24, 15
79; CHECK: ldi r25, 2
80; CHECK: ldi r18, 128
81; CHECK: ldi r19, 132
82; CHECK: ldi r20, 30
83; CHECK: ldi r21, 2
84; AVR6:  call foo32_1
85; AVR2:  rcall foo32_1
86    %result1 = call i32 @foo32_1(i32 34554432, i32 35554432)
87    ret i32 %result1
88}
89
90define i32 @calli32_stack() {
91; CHECK-LABEL: calli32_stack:
92; CHECK: ldi [[REG1:r[0-9]+]], 15
93; CHECK: ldi [[REG2:r[0-9]+]], 2
94; CHECK: std Z+4, [[REG2]]
95; CHECK: std Z+3, [[REG1]]
96; CHECK: ldi [[REG1:r[0-9]+]], 64
97; CHECK: ldi [[REG2:r[0-9]+]], 66
98; CHECK: std Z+2, [[REG2]]
99; CHECK: std Z+1, [[REG1]]
100; AVR6:  call foo32_2
101; AVR2:  rcall foo32_2
102    %result1 = call i32 @foo32_2(i32 1, i32 2, i32 3, i32 4, i32 34554432)
103    ret i32 %result1
104}
105
106define i64 @calli64_reg() {
107; CHECK-LABEL: calli64_reg:
108; CHECK: ldi r18, 255
109; CHECK: ldi r19, 255
110; CHECK: ldi r20, 155
111; CHECK: ldi r21, 88
112; CHECK: ldi r22, 76
113; CHECK: ldi r23, 73
114; CHECK: ldi r24, 31
115; CHECK: ldi r25, 242
116; AVR6:  call foo64_1
117; AVR2:  rcall foo64_1
118    %result1 = call i64 @foo64_1(i64 17446744073709551615)
119    ret i64 %result1
120}
121
122define i64 @calli64_stack() {
123; CHECK-LABEL: calli64_stack:
124
125; CHECK: ldi [[REG1:r[0-9]+]], 31
126; CHECK: ldi [[REG2:r[0-9]+]], 242
127; CHECK: std Z+8, [[REG2]]
128; CHECK: std Z+7, [[REG1]]
129; CHECK: ldi [[REG1:r[0-9]+]], 76
130; CHECK: ldi [[REG2:r[0-9]+]], 73
131; CHECK: std Z+6, [[REG2]]
132; CHECK: std Z+5, [[REG1]]
133; CHECK: ldi [[REG1:r[0-9]+]], 155
134; CHECK: ldi [[REG2:r[0-9]+]], 88
135; CHECK: std Z+4, [[REG2]]
136; CHECK: std Z+3, [[REG1]]
137; CHECK: ldi [[REG1:r[0-9]+]], 255
138; CHECK: ldi [[REG2:r[0-9]+]], 255
139; CHECK: std Z+2, [[REG2]]
140; CHECK: std Z+1, [[REG1]]
141; AVR6:  call foo64_2
142; AVR2:  rcall foo64_2
143    %result1 = call i64 @foo64_2(i64 1, i64 2, i64 17446744073709551615)
144    ret i64 %result1
145}
146
147; Test passing arguments through the stack when the call frame is allocated
148; in the prologue.
149declare void @foo64_3(i64, i64, i64, i8, ptr)
150
151define void @testcallprologue() {
152; CHECK-LABEL: testcallprologue:
153; CHECK: push r28
154; CHECK: push r29
155; CHECK: sbiw r28, 27
156; CHECK: ldi [[REG1:r[0-9]+]], 88
157; CHECK: std Y+9, [[REG1]]
158; CHECK: ldi [[REG1:r[0-9]+]], 11
159; CHECK: ldi [[REG2:r[0-9]+]], 10
160; CHECK: std Y+8, [[REG2]]
161; CHECK: std Y+7, [[REG1]]
162; CHECK: ldi [[REG1:r[0-9]+]], 13
163; CHECK: ldi [[REG2:r[0-9]+]], 12
164; CHECK: std Y+6, [[REG2]]
165; CHECK: std Y+5, [[REG1]]
166; CHECK: ldi [[REG1:r[0-9]+]], 15
167; CHECK: ldi [[REG2:r[0-9]+]], 14
168; CHECK: std Y+4, [[REG2]]
169; CHECK: std Y+3, [[REG1]]
170; CHECK: ldi [[REG1:r[0-9]+]], 8
171; CHECK: ldi [[REG2:r[0-9]+]], 9
172; CHECK: std Y+2, [[REG2]]
173; CHECK: std Y+1, [[REG1]]
174; CHECK: pop r29
175; CHECK: pop r28
176  %p = alloca [8 x i16]
177  %arraydecay = getelementptr inbounds [8 x i16], ptr %p, i16 0, i16 0
178  call void @foo64_3(i64 723685415333071112, i64 723685415333071112, i64 723685415333071112, i8 88, ptr %arraydecay)
179  ret void
180}
181
182define i32 @icall(ptr addrspace(1) %foo) {
183; CHECK-LABEL: icall:
184; AVR6:  movw r30, r24
185; AVR2:  mov r30, r24
186; AVR2:  mov r31, r25
187; CHECK: ldi r22, 147
188; CHECK: ldi r23, 248
189; CHECK: ldi r24, 214
190; CHECK: ldi r25, 198
191; CHECK: icall
192; CHECK: subi r22, 251
193; CHECK: sbci r23, 255
194; CHECK: sbci r24, 255
195; CHECK: sbci r25, 255
196  %1 = call i32 %foo(i32 3335977107)
197  %2 = add nsw i32 %1, 5
198  ret i32 %2
199}
200
201; Calling external functions (like __divsf3) require extra processing for
202; arguments and return values in the LowerCall function.
203declare i32 @foofloat(float)
204
205define i32 @externcall(float %a, float %b) {
206; CHECK-LABEL: externcall:
207; AVR6:  movw [[REG0:(r[0-9]+|[XYZ])]], r24
208; AVR6:  movw [[REG1:(r[0-9]+|[XYZ])]], r22
209; AVR6:  movw r22, r18
210; AVR6:  movw r24, r20
211; AVR6:  movw r18, [[REG1]]
212; AVR6:  movw r20, [[REG0]]
213; AVR6:  call __divsf3
214; AVR6:  call foofloat
215; AVR2:  mov [[REG0:(r[0-9]+)]], r24
216; AVR2:  mov [[REG1:(r[0-9]+)]], r25
217; AVR2:  mov [[REG2:(r[0-9]+)]], r22
218; AVR2:  mov [[REG3:(r[0-9]+)]], r23
219; AVR2:  mov r22, r18
220; AVR2:  mov r23, r19
221; AVR2:  mov r24, r20
222; AVR2:  mov r25, r21
223; AVR2:  mov r18, [[REG2]]
224; AVR2:  mov r19, [[REG3]]
225; AVR2:  mov r20, [[REG0]]
226; AVR2:  mov r21, [[REG1]]
227; AVR2:  rcall __divsf3
228; AVR2:  rcall foofloat
229; CHECK: subi r22, 251
230; CHECK: sbci r23, 255
231; CHECK: sbci r24, 255
232; CHECK: sbci r25, 255
233  %1 = fdiv float %b, %a
234  %2 = call i32 @foofloat(float %1)
235  %3 = add nsw i32 %2, 5
236  ret i32 %3
237}
238