xref: /llvm-project/llvm/test/CodeGen/SPARC/bigreturn.ll (revision ff9af4c43ad71eeba2cabe99609cfaa0fd54c1d0)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=sparc -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck --check-prefix=SPARC %s
3; RUN: llc < %s -mtriple=sparc64 -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck --check-prefix=SPARC64 %s
4
5;; Structs up to six registers in size can be returned in registers.
6;; Note that the maximum return size and member placement is NOT
7;; compatible with the C ABI - see SparcCallingConv.td.
8define { i32, i32 } @ret_i32_pair(i32 %a0, i32 %a1, ptr %p, ptr %q) {
9; SPARC-LABEL: ret_i32_pair:
10; SPARC:         .cfi_startproc
11; SPARC-NEXT:  ! %bb.0:
12; SPARC-NEXT:    save %sp, -96, %sp
13; SPARC-NEXT:    .cfi_def_cfa_register %fp
14; SPARC-NEXT:    .cfi_window_save
15; SPARC-NEXT:    .cfi_register %o7, %i7
16; SPARC-NEXT:    ld [%i2], %i0
17; SPARC-NEXT:    st %g0, [%i2]
18; SPARC-NEXT:    ld [%i3], %i1
19; SPARC-NEXT:    restore
20; SPARC-NEXT:    retl
21; SPARC-NEXT:    nop
22;
23; SPARC64-LABEL: ret_i32_pair:
24; SPARC64:         .cfi_startproc
25; SPARC64-NEXT:  ! %bb.0:
26; SPARC64-NEXT:    save %sp, -128, %sp
27; SPARC64-NEXT:    .cfi_def_cfa_register %fp
28; SPARC64-NEXT:    .cfi_window_save
29; SPARC64-NEXT:    .cfi_register %o7, %i7
30; SPARC64-NEXT:    ld [%i2], %i0
31; SPARC64-NEXT:    st %g0, [%i2]
32; SPARC64-NEXT:    ld [%i3], %i1
33; SPARC64-NEXT:    restore
34; SPARC64-NEXT:    retl
35; SPARC64-NEXT:    nop
36  %r1 = load i32, ptr %p
37  %rv1 = insertvalue { i32, i32 } undef, i32 %r1, 0
38  store i32 0, ptr %p
39  %r2 = load i32, ptr %q
40  %rv2 = insertvalue { i32, i32 } %rv1, i32 %r2, 1
41  ret { i32, i32 } %rv2
42}
43
44define void @call_ret_i32_pair(ptr %i0) {
45; SPARC-LABEL: call_ret_i32_pair:
46; SPARC:         .cfi_startproc
47; SPARC-NEXT:  ! %bb.0:
48; SPARC-NEXT:    save %sp, -96, %sp
49; SPARC-NEXT:    .cfi_def_cfa_register %fp
50; SPARC-NEXT:    .cfi_window_save
51; SPARC-NEXT:    .cfi_register %o7, %i7
52; SPARC-NEXT:    call ret_i32_pair
53; SPARC-NEXT:    nop
54; SPARC-NEXT:    st %o0, [%i0]
55; SPARC-NEXT:    st %o1, [%i0]
56; SPARC-NEXT:    restore
57; SPARC-NEXT:    retl
58; SPARC-NEXT:    nop
59;
60; SPARC64-LABEL: call_ret_i32_pair:
61; SPARC64:         .cfi_startproc
62; SPARC64-NEXT:  ! %bb.0:
63; SPARC64-NEXT:    save %sp, -176, %sp
64; SPARC64-NEXT:    .cfi_def_cfa_register %fp
65; SPARC64-NEXT:    .cfi_window_save
66; SPARC64-NEXT:    .cfi_register %o7, %i7
67; SPARC64-NEXT:    call ret_i32_pair
68; SPARC64-NEXT:    nop
69; SPARC64-NEXT:    st %o0, [%i0]
70; SPARC64-NEXT:    st %o1, [%i0]
71; SPARC64-NEXT:    restore
72; SPARC64-NEXT:    retl
73; SPARC64-NEXT:    nop
74  %rv = call { i32, i32 } @ret_i32_pair(i32 undef, i32 undef,
75                                        ptr undef, ptr undef)
76  %e0 = extractvalue { i32, i32 } %rv, 0
77  store volatile i32 %e0, ptr %i0
78  %e1 = extractvalue { i32, i32 } %rv, 1
79  store i32 %e1, ptr %i0
80  ret void
81}
82
83;; Functions returning structs more than six registers' worth of space
84;; should be automatically treated as an sret function.
85declare { [16 x i32] } @ret_i32_arr(i32 %input)
86
87define i32 @call_ret_i32_arr(i32 %0) {
88; SPARC-LABEL: call_ret_i32_arr:
89; SPARC:         .cfi_startproc
90; SPARC-NEXT:  ! %bb.0:
91; SPARC-NEXT:    save %sp, -160, %sp
92; SPARC-NEXT:    .cfi_def_cfa_register %fp
93; SPARC-NEXT:    .cfi_window_save
94; SPARC-NEXT:    .cfi_register %o7, %i7
95; SPARC-NEXT:    add %fp, -64, %i1
96; SPARC-NEXT:    st %i1, [%sp+64]
97; SPARC-NEXT:    mov %i0, %o0
98; SPARC-NEXT:    call ret_i32_arr
99; SPARC-NEXT:    nop
100; SPARC-NEXT:    unimp 64
101; SPARC-NEXT:    ld [%fp+-4], %i0
102; SPARC-NEXT:    restore
103; SPARC-NEXT:    retl
104; SPARC-NEXT:    nop
105;
106; SPARC64-LABEL: call_ret_i32_arr:
107; SPARC64:         .cfi_startproc
108; SPARC64-NEXT:  ! %bb.0:
109; SPARC64-NEXT:    save %sp, -240, %sp
110; SPARC64-NEXT:    .cfi_def_cfa_register %fp
111; SPARC64-NEXT:    .cfi_window_save
112; SPARC64-NEXT:    .cfi_register %o7, %i7
113; SPARC64-NEXT:    add %fp, 1983, %o0
114; SPARC64-NEXT:    mov %i0, %o1
115; SPARC64-NEXT:    call ret_i32_arr
116; SPARC64-NEXT:    nop
117; SPARC64-NEXT:    ld [%fp+2043], %i0
118; SPARC64-NEXT:    restore
119; SPARC64-NEXT:    retl
120; SPARC64-NEXT:    nop
121  %2 = call { [16 x i32] } @ret_i32_arr(i32 %0)
122  %3 = extractvalue { [16 x i32] } %2, 0
123  %4 = extractvalue [16 x i32] %3, 15
124  ret i32 %4
125}
126
127;; Structs up to six registers in size can be returned in registers.
128;; Note that the maximum return size and member placement is NOT
129;; compatible with the C ABI - see SparcCallingConv.td.
130define { i64, i64 } @ret_i64_pair(i32 %a0, i32 %a1, ptr %p, ptr %q) {
131; SPARC-LABEL: ret_i64_pair:
132; SPARC:         .cfi_startproc
133; SPARC-NEXT:  ! %bb.0:
134; SPARC-NEXT:    save %sp, -96, %sp
135; SPARC-NEXT:    .cfi_def_cfa_register %fp
136; SPARC-NEXT:    .cfi_window_save
137; SPARC-NEXT:    .cfi_register %o7, %i7
138; SPARC-NEXT:    mov %g0, %i4
139; SPARC-NEXT:    ldd [%i2], %i0
140; SPARC-NEXT:    mov %g0, %i5
141; SPARC-NEXT:    std %i4, [%i2]
142; SPARC-NEXT:    ldd [%i3], %i2
143; SPARC-NEXT:    restore
144; SPARC-NEXT:    retl
145; SPARC-NEXT:    nop
146;
147; SPARC64-LABEL: ret_i64_pair:
148; SPARC64:         .cfi_startproc
149; SPARC64-NEXT:  ! %bb.0:
150; SPARC64-NEXT:    save %sp, -128, %sp
151; SPARC64-NEXT:    .cfi_def_cfa_register %fp
152; SPARC64-NEXT:    .cfi_window_save
153; SPARC64-NEXT:    .cfi_register %o7, %i7
154; SPARC64-NEXT:    ldx [%i2], %i0
155; SPARC64-NEXT:    stx %g0, [%i2]
156; SPARC64-NEXT:    ldx [%i3], %i1
157; SPARC64-NEXT:    restore
158; SPARC64-NEXT:    retl
159; SPARC64-NEXT:    nop
160  %r1 = load i64, ptr %p
161  %rv1 = insertvalue { i64, i64 } undef, i64 %r1, 0
162  store i64 0, ptr %p
163  %r2 = load i64, ptr %q
164  %rv2 = insertvalue { i64, i64 } %rv1, i64 %r2, 1
165  ret { i64, i64 } %rv2
166}
167
168define void @call_ret_i64_pair(ptr %i0) {
169; SPARC-LABEL: call_ret_i64_pair:
170; SPARC:         .cfi_startproc
171; SPARC-NEXT:  ! %bb.0:
172; SPARC-NEXT:    save %sp, -96, %sp
173; SPARC-NEXT:    .cfi_def_cfa_register %fp
174; SPARC-NEXT:    .cfi_window_save
175; SPARC-NEXT:    .cfi_register %o7, %i7
176; SPARC-NEXT:    call ret_i64_pair
177; SPARC-NEXT:    nop
178; SPARC-NEXT:    ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1
179; SPARC-NEXT:    ! kill: def $o2 killed $o2 killed $o2_o3 def $o2_o3
180; SPARC-NEXT:    ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1
181; SPARC-NEXT:    std %o0, [%i0]
182; SPARC-NEXT:    ! kill: def $o3 killed $o3 killed $o2_o3 def $o2_o3
183; SPARC-NEXT:    std %o2, [%i0]
184; SPARC-NEXT:    restore
185; SPARC-NEXT:    retl
186; SPARC-NEXT:    nop
187;
188; SPARC64-LABEL: call_ret_i64_pair:
189; SPARC64:         .cfi_startproc
190; SPARC64-NEXT:  ! %bb.0:
191; SPARC64-NEXT:    save %sp, -176, %sp
192; SPARC64-NEXT:    .cfi_def_cfa_register %fp
193; SPARC64-NEXT:    .cfi_window_save
194; SPARC64-NEXT:    .cfi_register %o7, %i7
195; SPARC64-NEXT:    call ret_i64_pair
196; SPARC64-NEXT:    nop
197; SPARC64-NEXT:    stx %o0, [%i0]
198; SPARC64-NEXT:    stx %o1, [%i0]
199; SPARC64-NEXT:    restore
200; SPARC64-NEXT:    retl
201; SPARC64-NEXT:    nop
202  %rv = call { i64, i64 } @ret_i64_pair(i32 undef, i32 undef,
203                                        ptr undef, ptr undef)
204  %e0 = extractvalue { i64, i64 } %rv, 0
205  store volatile i64 %e0, ptr %i0
206  %e1 = extractvalue { i64, i64 } %rv, 1
207  store i64 %e1, ptr %i0
208  ret void
209}
210
211;; Functions returning structs more than six registers' worth of space
212;; should be automatically treated as an sret function.
213declare { [16 x i64] } @ret_i64_arr(i64 %input)
214
215define i64 @call_ret_i64_arr(i64 %0) {
216; SPARC-LABEL: call_ret_i64_arr:
217; SPARC:         .cfi_startproc
218; SPARC-NEXT:  ! %bb.0:
219; SPARC-NEXT:    save %sp, -224, %sp
220; SPARC-NEXT:    .cfi_def_cfa_register %fp
221; SPARC-NEXT:    .cfi_window_save
222; SPARC-NEXT:    .cfi_register %o7, %i7
223; SPARC-NEXT:    add %fp, -128, %i2
224; SPARC-NEXT:    st %i2, [%sp+64]
225; SPARC-NEXT:    mov %i0, %o0
226; SPARC-NEXT:    mov %i1, %o1
227; SPARC-NEXT:    call ret_i64_arr
228; SPARC-NEXT:    nop
229; SPARC-NEXT:    unimp 128
230; SPARC-NEXT:    ldd [%fp+-8], %i0
231; SPARC-NEXT:    restore
232; SPARC-NEXT:    retl
233; SPARC-NEXT:    nop
234;
235; SPARC64-LABEL: call_ret_i64_arr:
236; SPARC64:         .cfi_startproc
237; SPARC64-NEXT:  ! %bb.0:
238; SPARC64-NEXT:    save %sp, -304, %sp
239; SPARC64-NEXT:    .cfi_def_cfa_register %fp
240; SPARC64-NEXT:    .cfi_window_save
241; SPARC64-NEXT:    .cfi_register %o7, %i7
242; SPARC64-NEXT:    add %fp, 1919, %o0
243; SPARC64-NEXT:    mov %i0, %o1
244; SPARC64-NEXT:    call ret_i64_arr
245; SPARC64-NEXT:    nop
246; SPARC64-NEXT:    ldx [%fp+2039], %i0
247; SPARC64-NEXT:    restore
248; SPARC64-NEXT:    retl
249; SPARC64-NEXT:    nop
250  %2 = call { [16 x i64] } @ret_i64_arr(i64 %0)
251  %3 = extractvalue { [16 x i64] } %2, 0
252  %4 = extractvalue [16 x i64] %3, 15
253  ret i64 %4
254}
255