1 ; RUN: llc < %s -march=sparc -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-BE
2 ; RUN: llc < %s -march=sparcel -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-LE
5 ; The save/restore frame is not strictly necessary here, but we would need to
6 ; refer to %o registers instead.
7 ; CHECK: save %sp, -96, %sp
8 ; CHECK: ld [%fp+96], [[R2:%[gilo][0-7]]]
9 ; CHECK: ld [%fp+92], [[R1:%[gilo][0-7]]]
10 ; CHECK: stb %i0, [%i4]
11 ; CHECK: stb %i1, [%i4]
12 ; CHECK: sth %i2, [%i4]
13 ; CHECK: st %i3, [%i4]
14 ; CHECK: st %i4, [%i4]
15 ; CHECK: st %i5, [%i4]
16 ; CHECK: st [[R1]], [%i4]
17 ; CHECK: st [[R2]], [%i4]
19 define void @intarg(i8 %a0, ; %i0
25 i32 signext %a6, ; [%fp+92]
29 %p16 = bitcast i8* %a4 to i16*
30 store i16 %a2, i16* %p16
31 %p32 = bitcast i8* %a4 to i32*
32 store i32 %a3, i32* %p32
33 %pp = bitcast i8* %a4 to i8**
34 store i8* %a4, i8** %pp
35 store i32 %a5, i32* %p32
36 store i32 %a6, i32* %p32
37 store i8* %a7, i8** %pp
41 ; CHECK-LABEL: call_intarg:
42 ; CHECK: save %sp, -104, %sp
43 ; Use %o0-%o5 for outgoing arguments
45 ; CHECK: st %i0, [%sp+92]
49 define void @call_intarg(i32 %i0, i8* %i1) {
50 call void @intarg(i8 0, i8 1, i16 2, i32 3, i8* undef, i32 5, i32 %i0, i8* %i1)
54 ;; Verify doubles starting with an even reg, starting with an odd reg,
55 ;; straddling the boundary of regs and mem, and floats in regs and mem.
57 ; CHECK-LABEL: floatarg:
58 ; CHECK: save %sp, -120, %sp
60 ; CHECK-NEXT: ld [%fp+92], %g3
61 ; CHECK-NEXT: mov %i4, %i5
62 ; CHECK-NEXT: std %g2, [%fp+-24]
63 ; CHECK-NEXT: mov %i3, %i4
64 ; CHECK-NEXT: std %i4, [%fp+-16]
65 ; CHECK-NEXT: std %i0, [%fp+-8]
66 ; CHECK-NEXT: st %i2, [%fp+-28]
67 ; CHECK-NEXT: ld [%fp+104], %f0
68 ; CHECK-NEXT: ldd [%fp+96], %f2
69 ; CHECK-NEXT: ld [%fp+-28], %f1
70 ; CHECK-NEXT: ldd [%fp+-8], %f4
71 ; CHECK-NEXT: ldd [%fp+-16], %f6
72 ; CHECK-NEXT: ldd [%fp+-24], %f8
73 ; CHECK-NEXT: fstod %f1, %f10
74 ; CHECK-NEXT: faddd %f4, %f10, %f4
75 ; CHECK-NEXT: faddd %f6, %f4, %f4
76 ; CHECK-NEXT: faddd %f8, %f4, %f4
77 ; CHECK-NEXT: faddd %f2, %f4, %f2
78 ; CHECK-NEXT: fstod %f0, %f0
79 ; CHECK-NEXT: faddd %f0, %f2, %f0
81 define double @floatarg(double %a0, ; %i0,%i1
83 double %a2, ; %i3, %i4
84 double %a3, ; %i5, [%fp+92] (using 4 bytes)
85 double %a4, ; [%fp+96] (using 8 bytes)
86 float %a5) { ; [%fp+104] (using 4 bytes)
87 %d1 = fpext float %a1 to double
88 %s1 = fadd double %a0, %d1
89 %s2 = fadd double %a2, %s1
90 %s3 = fadd double %a3, %s2
91 %s4 = fadd double %a4, %s3
92 %d5 = fpext float %a5 to double
93 %s5 = fadd double %d5, %s4
97 ; CHECK-LABEL: call_floatarg:
98 ; CHECK: save %sp, -112, %sp
100 ; CHECK-NEXT: mov %i1, %o0
101 ; CHECK-NEXT: st %i0, [%sp+104]
102 ; CHECK-NEXT: std %o0, [%sp+96]
103 ; CHECK-NEXT: st %o1, [%sp+92]
104 ; CHECK-NEXT: mov %i0, %o2
105 ; CHECK-NEXT: mov %o0, %o3
106 ; CHECK-NEXT: mov %o1, %o4
107 ; CHECK-NEXT: mov %o0, %o5
108 ; CHECK-NEXT: call floatarg
109 ; CHECK: std %f0, [%i4]
111 define void @call_floatarg(float %f1, double %d2, float %f5, double *%p) {
112 %r = call double @floatarg(double %d2, float %f1, double %d2, double %d2,
113 double %d2, float %f1)
114 store double %r, double* %p
118 ;; i64 arguments should effectively work the same as double: split
119 ;; into two locations. This is different for little-endian vs big
120 ;; endian, since the 64-bit math needs to be split
121 ; CHECK-LABEL: i64arg:
122 ; CHECK: save %sp, -96, %sp
123 ; CHECK-BE: ld [%fp+100], %g2
124 ; CHECK-BE-NEXT: ld [%fp+96], %g3
125 ; CHECK-BE-NEXT: ld [%fp+92], %g4
126 ; CHECK-BE-NEXT: addcc %i1, %i2, %i1
127 ; CHECK-BE-NEXT: addxcc %i0, 0, %i0
128 ; CHECK-BE-NEXT: addcc %i4, %i1, %i1
129 ; CHECK-BE-NEXT: addxcc %i3, %i0, %i0
130 ; CHECK-BE-NEXT: addcc %g4, %i1, %i1
131 ; CHECK-BE-NEXT: ld [%fp+104], %i2
132 ; CHECK-BE-NEXT: addxcc %i5, %i0, %i0
133 ; CHECK-BE-NEXT: addcc %g2, %i1, %i1
134 ; CHECK-BE-NEXT: addxcc %g3, %i0, %i0
135 ; CHECK-BE-NEXT: addcc %i2, %i1, %i1
136 ; CHECK-BE-NEXT: addxcc %i0, 0, %i0
138 ; CHECK-LE: ld [%fp+96], %g2
139 ; CHECK-LE-NEXT: ld [%fp+100], %g3
140 ; CHECK-LE-NEXT: ld [%fp+92], %g4
141 ; CHECK-LE-NEXT: addcc %i0, %i2, %i0
142 ; CHECK-LE-NEXT: addxcc %i1, 0, %i1
143 ; CHECK-LE-NEXT: addcc %i3, %i0, %i0
144 ; CHECK-LE-NEXT: addxcc %i4, %i1, %i1
145 ; CHECK-LE-NEXT: addcc %i5, %i0, %i0
146 ; CHECK-LE-NEXT: ld [%fp+104], %i2
147 ; CHECK-LE-NEXT: addxcc %g4, %i1, %i1
148 ; CHECK-LE-NEXT: addcc %g2, %i0, %i0
149 ; CHECK-LE-NEXT: addxcc %g3, %i1, %i1
150 ; CHECK-LE-NEXT: addcc %i2, %i0, %i0
151 ; CHECK-LE-NEXT: addxcc %i1, 0, %i1
152 ; CHECK-NEXT: restore
155 define i64 @i64arg(i64 %a0, ; %i0,%i1
158 i64 %a3, ; %i5, [%fp+92] (using 4 bytes)
159 i64 %a4, ; [%fp+96] (using 8 bytes)
160 i32 %a5) { ; [%fp+104] (using 4 bytes)
161 %a1L = zext i32 %a1 to i64
162 %s1 = add i64 %a0, %a1L
163 %s2 = add i64 %a2, %s1
164 %s3 = add i64 %a3, %s2
165 %s4 = add i64 %a4, %s3
166 %a5L = zext i32 %a5 to i64
167 %s5 = add i64 %a5L, %s4
171 ; CHECK-LABEL: call_i64arg:
172 ; CHECK: save %sp, -112, %sp
173 ; CHECK: st %i0, [%sp+104]
174 ; CHECK-NEXT: st %i2, [%sp+100]
175 ; CHECK-NEXT: st %i1, [%sp+96]
176 ; CHECK-NEXT: st %i2, [%sp+92]
177 ; CHECK-NEXT: mov %i1, %o0
178 ; CHECK-NEXT: mov %i2, %o1
179 ; CHECK-NEXT: mov %i0, %o2
180 ; CHECK-NEXT: mov %i1, %o3
181 ; CHECK-NEXT: mov %i2, %o4
182 ; CHECK-NEXT: mov %i1, %o5
183 ; CHECK-NEXT: call i64arg
184 ; CHECK: std %o0, [%i3]
185 ; CHECK-NEXT: restore
187 define void @call_i64arg(i32 %a0, i64 %a1, i64* %p) {
188 %r = call i64 @i64arg(i64 %a1, i32 %a0, i64 %a1, i64 %a1, i64 %a1, i32 %a0)
189 store i64 %r, i64* %p