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 19 define 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 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) 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 81 define 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 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 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 155 define 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 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 190 ret void 191 } 192