• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3
4; CHECK-LABEL: intarg:
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]
18; CHECK: restore
19define void @intarg(i8  %a0,   ; %i0
20                    i8  %a1,   ; %i1
21                    i16 %a2,   ; %i2
22                    i32 %a3,   ; %i3
23                    i8* %a4,   ; %i4
24                    i32 %a5,   ; %i5
25                    i32 signext %a6,   ; [%fp+92]
26                    i8* %a7) { ; [%fp+96]
27  store i8 %a0, i8* %a4
28  store i8 %a1, i8* %a4
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
38  ret void
39}
40
41; CHECK-LABEL: call_intarg:
42; CHECK: save %sp, -104, %sp
43; Use %o0-%o5 for outgoing arguments
44; CHECK: mov 5, %o5
45; CHECK: st %i0, [%sp+92]
46; CHECK: call intarg
47; CHECK-NOT: add %sp
48; CHECK: restore
49define 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)
51  ret void
52}
53
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.
56;
57; CHECK-LABEL: floatarg:
58; CHECK: save %sp, -120, %sp
59; CHECK: mov %i5, %g2
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
80; CHECK-NEXT: restore
81define double @floatarg(double %a0,   ; %i0,%i1
82                        float %a1,    ; %i2
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
94  ret double %s5
95}
96
97; CHECK-LABEL: call_floatarg:
98; CHECK: save %sp, -112, %sp
99; CHECK: mov %i2, %o1
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]
110; CHECK: restore
111define 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
115  ret void
116}
117
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
137;
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
153
154
155define i64 @i64arg(i64 %a0,    ; %i0,%i1
156		   i32 %a1,    ; %i2
157		   i64 %a2,    ; %i3, %i4
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
168  ret i64 %s5
169}
170
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
186
187define 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
190  ret void
191}
192