1 ; RUN: llc < %s -march=sparc -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck %s --check-prefix=CHECK --check-prefix=HARD --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=HARD --check-prefix=CHECK-LE 3 ; RUN: llc < %s -march=sparc -disable-sparc-delay-filler -disable-sparc-leaf-proc -mattr=soft-float | FileCheck %s --check-prefix=CHECK --check-prefix=SOFT --check-prefix=CHECK-BE 4 5 ; CHECK-LABEL: intarg: 6 ; The save/restore frame is not strictly necessary here, but we would need to 7 ; refer to %o registers instead. 8 ; CHECK: save %sp, -96, %sp 9 ; CHECK: ld [%fp+96], [[R2:%[gilo][0-7]]] 10 ; CHECK: ld [%fp+92], [[R1:%[gilo][0-7]]] 11 ; CHECK: stb %i0, [%i4] 12 ; CHECK: stb %i1, [%i4] 13 ; CHECK: sth %i2, [%i4] 14 ; CHECK: st %i3, [%i4] 15 ; CHECK: st %i4, [%i4] 16 ; CHECK: st %i5, [%i4] 17 ; CHECK: st [[R1]], [%i4] 18 ; CHECK: st [[R2]], [%i4] 19 ; CHECK: restore 20 define void @intarg(i8 %a0, ; %i0 21 i8 %a1, ; %i1 22 i16 %a2, ; %i2 23 i32 %a3, ; %i3 24 i8* %a4, ; %i4 25 i32 %a5, ; %i5 26 i32 signext %a6, ; [%fp+92] 27 i8* %a7) { ; [%fp+96] 28 store i8 %a0, i8* %a4 29 store i8 %a1, i8* %a4 30 %p16 = bitcast i8* %a4 to i16* 31 store i16 %a2, i16* %p16 32 %p32 = bitcast i8* %a4 to i32* 33 store i32 %a3, i32* %p32 34 %pp = bitcast i8* %a4 to i8** 35 store i8* %a4, i8** %pp 36 store i32 %a5, i32* %p32 37 store i32 %a6, i32* %p32 38 store i8* %a7, i8** %pp 39 ret void 40 } 41 42 ; CHECK-LABEL: call_intarg: 43 ; CHECK: save %sp, -104, %sp 44 ; Use %o0-%o5 for outgoing arguments 45 ; CHECK: mov 5, %o5 46 ; CHECK: st %i0, [%sp+92] 47 ; CHECK: call intarg 48 ; CHECK-NOT: add %sp 49 ; CHECK: restore 50 define void @call_intarg(i32 %i0, i8* %i1) { 51 call void @intarg(i8 0, i8 1, i16 2, i32 3, i8* undef, i32 5, i32 %i0, i8* %i1) 52 ret void 53 } 54 55 ;; Verify doubles starting with an even reg, starting with an odd reg, 56 ;; straddling the boundary of regs and mem, and floats in regs and mem. 57 ; 58 ; CHECK-LABEL: floatarg: 59 ; HARD: save %sp, -120, %sp 60 ; HARD: mov %i5, %g2 61 ; HARD-NEXT: ld [%fp+92], %g3 62 ; HARD-NEXT: mov %i4, %i5 63 ; HARD-NEXT: ! kill 64 ; HARD-NEXT: std %g2, [%fp+-24] 65 ; HARD-NEXT: mov %i3, %i4 66 ; HARD-NEXT: std %i4, [%fp+-16] 67 ; HARD-NEXT: ! kill 68 ; HARD-NEXT: std %i0, [%fp+-8] 69 ; HARD-NEXT: st %i2, [%fp+-28] 70 ; HARD-NEXT: ld [%fp+104], %f0 71 ; HARD-NEXT: ldd [%fp+96], %f2 72 ; HARD-NEXT: ld [%fp+-28], %f1 73 ; HARD-NEXT: ldd [%fp+-8], %f4 74 ; HARD-NEXT: ldd [%fp+-16], %f6 75 ; HARD-NEXT: ldd [%fp+-24], %f8 76 ; HARD-NEXT: fstod %f1, %f10 77 ; HARD-NEXT: faddd %f4, %f10, %f4 78 ; HARD-NEXT: faddd %f6, %f4, %f4 79 ; HARD-NEXT: faddd %f8, %f4, %f4 80 ; HARD-NEXT: faddd %f2, %f4, %f2 81 ; HARD-NEXT: fstod %f0, %f0 82 ; HARD-NEXT: faddd %f0, %f2, %f0 83 ; SOFT: save %sp, -96, %sp 84 ; SOFT: ld [%fp+104], %l0 85 ; SOFT-NEXT: ld [%fp+96], %l1 86 ; SOFT-NEXT: ld [%fp+100], %l2 87 ; SOFT-NEXT: ld [%fp+92], %l3 88 ; SOFT-NEXT: mov %i2, %o0 89 ; SOFT-NEXT: call __extendsfdf2 90 ; SOFT-NEXT: nop 91 ; SOFT-NEXT: mov %o0, %i2 92 ; SOFT-NEXT: mov %o1, %g2 93 ; SOFT-NEXT: mov %i0, %o0 94 ; SOFT-NEXT: mov %i1, %o1 95 ; SOFT-NEXT: mov %i2, %o2 96 ; SOFT-NEXT: mov %g2, %o3 97 ; SOFT-NEXT: call __adddf3 98 ; SOFT-NEXT: nop 99 ; SOFT-NEXT: mov %o0, %i0 100 ; SOFT-NEXT: mov %o1, %i1 101 ; SOFT-NEXT: mov %i3, %o0 102 ; SOFT-NEXT: mov %i4, %o1 103 ; SOFT-NEXT: mov %i0, %o2 104 ; SOFT-NEXT: mov %i1, %o3 105 ; SOFT-NEXT: call __adddf3 106 ; SOFT-NEXT: nop 107 ; SOFT-NEXT: mov %o0, %i0 108 ; SOFT-NEXT: mov %o1, %i1 109 ; SOFT-NEXT: mov %i5, %o0 110 ; SOFT-NEXT: mov %l3, %o1 111 ; SOFT-NEXT: mov %i0, %o2 112 ; SOFT-NEXT: mov %i1, %o3 113 ; SOFT-NEXT: call __adddf3 114 ; SOFT-NEXT: nop 115 ; SOFT-NEXT: mov %o0, %i0 116 ; SOFT-NEXT: mov %o1, %i1 117 ; SOFT-NEXT: mov %l1, %o0 118 ; SOFT-NEXT: mov %l2, %o1 119 ; SOFT-NEXT: mov %i0, %o2 120 ; SOFT-NEXT: mov %i1, %o3 121 ; SOFT-NEXT: call __adddf3 122 ; SOFT-NEXT: nop 123 ; SOFT-NEXT: mov %o0, %i0 124 ; SOFT-NEXT: mov %o1, %i1 125 ; SOFT-NEXT: mov %l0, %o0 126 ; SOFT-NEXT: call __extendsfdf2 127 ; SOFT-NEXT: nop 128 ; SOFT-NEXT: mov %i0, %o2 129 ; SOFT-NEXT: mov %i1, %o3 130 ; SOFT-NEXT: call __adddf3 131 ; SOFT-NEXT: nop 132 ; SOFT-NEXT: mov %o0, %i0 133 ; SOFT-NEXT: mov %o1, %i1 134 ; CHECK: restore 135 define double @floatarg(double %a0, ; %i0,%i1 136 float %a1, ; %i2 137 double %a2, ; %i3, %i4 138 double %a3, ; %i5, [%fp+92] (using 4 bytes) 139 double %a4, ; [%fp+96] (using 8 bytes) 140 float %a5) { ; [%fp+104] (using 4 bytes) 141 %d1 = fpext float %a1 to double 142 %s1 = fadd double %a0, %d1 143 %s2 = fadd double %a2, %s1 144 %s3 = fadd double %a3, %s2 145 %s4 = fadd double %a4, %s3 146 %d5 = fpext float %a5 to double 147 %s5 = fadd double %d5, %s4 148 ret double %s5 149 } 150 151 ; CHECK-LABEL: call_floatarg: 152 ; HARD: save %sp, -112, %sp 153 ; HARD: mov %i2, %o1 154 ; HARD-NEXT: mov %i1, %o0 155 ; HARD-NEXT: st %i0, [%sp+104] 156 ; HARD-NEXT: std %o0, [%sp+96] 157 ; HARD-NEXT: st %o1, [%sp+92] 158 ; HARD-NEXT: mov %i0, %o2 159 ; HARD-NEXT: mov %o0, %o3 160 ; HARD-NEXT: mov %o1, %o4 161 ; HARD-NEXT: mov %o0, %o5 162 ; HARD-NEXT: call floatarg 163 ; HARD: std %f0, [%i4] 164 ; SOFT: st %i0, [%sp+104] 165 ; SOFT-NEXT: st %i2, [%sp+100] 166 ; SOFT-NEXT: st %i1, [%sp+96] 167 ; SOFT-NEXT: st %i2, [%sp+92] 168 ; SOFT-NEXT: mov %i1, %o0 169 ; SOFT-NEXT: mov %i2, %o1 170 ; SOFT-NEXT: mov %i0, %o2 171 ; SOFT-NEXT: mov %i1, %o3 172 ; SOFT-NEXT: mov %i2, %o4 173 ; SOFT-NEXT: mov %i1, %o5 174 ; SOFT-NEXT: call floatarg 175 ; SOFT: std %o0, [%i4] 176 ; CHECK: restore 177 define void @call_floatarg(float %f1, double %d2, float %f5, double *%p) { 178 %r = call double @floatarg(double %d2, float %f1, double %d2, double %d2, 179 double %d2, float %f1) 180 store double %r, double* %p 181 ret void 182 } 183 184 ;; i64 arguments should effectively work the same as double: split 185 ;; into two locations. This is different for little-endian vs big 186 ;; endian, since the 64-bit math needs to be split 187 ; CHECK-LABEL: i64arg: 188 ; CHECK: save %sp, -96, %sp 189 ; CHECK-BE: ld [%fp+100], %g2 190 ; CHECK-BE-NEXT: ld [%fp+96], %g3 191 ; CHECK-BE-NEXT: ld [%fp+92], %g4 192 ; CHECK-BE-NEXT: addcc %i1, %i2, %i1 193 ; CHECK-BE-NEXT: addxcc %i0, 0, %i0 194 ; CHECK-BE-NEXT: addcc %i4, %i1, %i1 195 ; CHECK-BE-NEXT: addxcc %i3, %i0, %i0 196 ; CHECK-BE-NEXT: addcc %g4, %i1, %i1 197 ; CHECK-BE-NEXT: ld [%fp+104], %i2 198 ; CHECK-BE-NEXT: addxcc %i5, %i0, %i0 199 ; CHECK-BE-NEXT: addcc %g2, %i1, %i1 200 ; CHECK-BE-NEXT: addxcc %g3, %i0, %i0 201 ; CHECK-BE-NEXT: addcc %i2, %i1, %i1 202 ; CHECK-BE-NEXT: addxcc %i0, 0, %i0 203 ; 204 ; CHECK-LE: ld [%fp+96], %g2 205 ; CHECK-LE-NEXT: ld [%fp+100], %g3 206 ; CHECK-LE-NEXT: ld [%fp+92], %g4 207 ; CHECK-LE-NEXT: addcc %i0, %i2, %i0 208 ; CHECK-LE-NEXT: addxcc %i1, 0, %i1 209 ; CHECK-LE-NEXT: addcc %i3, %i0, %i0 210 ; CHECK-LE-NEXT: addxcc %i4, %i1, %i1 211 ; CHECK-LE-NEXT: addcc %i5, %i0, %i0 212 ; CHECK-LE-NEXT: ld [%fp+104], %i2 213 ; CHECK-LE-NEXT: addxcc %g4, %i1, %i1 214 ; CHECK-LE-NEXT: addcc %g2, %i0, %i0 215 ; CHECK-LE-NEXT: addxcc %g3, %i1, %i1 216 ; CHECK-LE-NEXT: addcc %i2, %i0, %i0 217 ; CHECK-LE-NEXT: addxcc %i1, 0, %i1 218 ; CHECK-NEXT: restore 219 220 221 define i64 @i64arg(i64 %a0, ; %i0,%i1 222 i32 %a1, ; %i2 223 i64 %a2, ; %i3, %i4 224 i64 %a3, ; %i5, [%fp+92] (using 4 bytes) 225 i64 %a4, ; [%fp+96] (using 8 bytes) 226 i32 %a5) { ; [%fp+104] (using 4 bytes) 227 %a1L = zext i32 %a1 to i64 228 %s1 = add i64 %a0, %a1L 229 %s2 = add i64 %a2, %s1 230 %s3 = add i64 %a3, %s2 231 %s4 = add i64 %a4, %s3 232 %a5L = zext i32 %a5 to i64 233 %s5 = add i64 %a5L, %s4 234 ret i64 %s5 235 } 236 237 ; CHECK-LABEL: call_i64arg: 238 ; CHECK: save %sp, -112, %sp 239 ; CHECK: st %i0, [%sp+104] 240 ; CHECK-NEXT: st %i2, [%sp+100] 241 ; CHECK-NEXT: st %i1, [%sp+96] 242 ; CHECK-NEXT: st %i2, [%sp+92] 243 ; CHECK-NEXT: mov %i1, %o0 244 ; CHECK-NEXT: mov %i2, %o1 245 ; CHECK-NEXT: mov %i0, %o2 246 ; CHECK-NEXT: mov %i1, %o3 247 ; CHECK-NEXT: mov %i2, %o4 248 ; CHECK-NEXT: mov %i1, %o5 249 ; CHECK-NEXT: call i64arg 250 ; CHECK: std %o0, [%i3] 251 ; CHECK-NEXT: restore 252 253 define void @call_i64arg(i32 %a0, i64 %a1, i64* %p) { 254 %r = call i64 @i64arg(i64 %a1, i32 %a0, i64 %a1, i64 %a1, i64 %a1, i32 %a0) 255 store i64 %r, i64* %p 256 ret void 257 } 258