1 ; RUN: llc -march=mipsel -pre-RA-sched=source < %s | FileCheck %s 2 3 ; All test functions do the same thing - they return the first variable 4 ; argument. 5 6 ; All CHECK's do the same thing - they check whether variable arguments from 7 ; registers are placed on correct stack locations, and whether the first 8 ; variable argument is returned from the correct stack location. 9 10 11 declare void @llvm.va_start(i8*) nounwind 12 declare void @llvm.va_end(i8*) nounwind 13 14 ; return int 15 define i32 @va1(i32 %a, ...) nounwind { 16 entry: 17 %a.addr = alloca i32, align 4 18 %ap = alloca i8*, align 4 19 %b = alloca i32, align 4 20 store i32 %a, i32* %a.addr, align 4 21 %ap1 = bitcast i8** %ap to i8* 22 call void @llvm.va_start(i8* %ap1) 23 %0 = va_arg i8** %ap, i32 24 store i32 %0, i32* %b, align 4 25 %ap2 = bitcast i8** %ap to i8* 26 call void @llvm.va_end(i8* %ap2) 27 %tmp = load i32* %b, align 4 28 ret i32 %tmp 29 30 ; CHECK-LABEL: va1: 31 ; CHECK: addiu $sp, $sp, -16 32 ; CHECK: sw $7, 28($sp) 33 ; CHECK: sw $6, 24($sp) 34 ; CHECK: sw $5, 20($sp) 35 ; CHECK: lw $2, 20($sp) 36 } 37 38 ; check whether the variable double argument will be accessed from the 8-byte 39 ; aligned location (i.e. whether the address is computed by adding 7 and 40 ; clearing lower 3 bits) 41 define double @va2(i32 %a, ...) nounwind { 42 entry: 43 %a.addr = alloca i32, align 4 44 %ap = alloca i8*, align 4 45 %b = alloca double, align 8 46 store i32 %a, i32* %a.addr, align 4 47 %ap1 = bitcast i8** %ap to i8* 48 call void @llvm.va_start(i8* %ap1) 49 %0 = va_arg i8** %ap, double 50 store double %0, double* %b, align 8 51 %ap2 = bitcast i8** %ap to i8* 52 call void @llvm.va_end(i8* %ap2) 53 %tmp = load double* %b, align 8 54 ret double %tmp 55 56 ; CHECK-LABEL: va2: 57 ; CHECK: addiu $sp, $sp, -16 58 ; CHECK: sw $7, 28($sp) 59 ; CHECK: sw $6, 24($sp) 60 ; CHECK: sw $5, 20($sp) 61 ; CHECK: addiu $[[R0:[0-9]+]], $sp, 20 62 ; CHECK: addiu $[[R1:[0-9]+]], $[[R0]], 7 63 ; CHECK: addiu $[[R2:[0-9]+]], $zero, -8 64 ; CHECK: and $[[R3:[0-9]+]], $[[R1]], $[[R2]] 65 ; CHECK: ldc1 $f0, 0($[[R3]]) 66 } 67 68 ; int 69 define i32 @va3(double %a, ...) nounwind { 70 entry: 71 %a.addr = alloca double, align 8 72 %ap = alloca i8*, align 4 73 %b = alloca i32, align 4 74 store double %a, double* %a.addr, align 8 75 %ap1 = bitcast i8** %ap to i8* 76 call void @llvm.va_start(i8* %ap1) 77 %0 = va_arg i8** %ap, i32 78 store i32 %0, i32* %b, align 4 79 %ap2 = bitcast i8** %ap to i8* 80 call void @llvm.va_end(i8* %ap2) 81 %tmp = load i32* %b, align 4 82 ret i32 %tmp 83 84 ; CHECK-LABEL: va3: 85 ; CHECK: addiu $sp, $sp, -16 86 ; CHECK: sw $7, 28($sp) 87 ; CHECK: sw $6, 24($sp) 88 ; CHECK: lw $2, 24($sp) 89 } 90 91 ; double 92 define double @va4(double %a, ...) nounwind { 93 entry: 94 %a.addr = alloca double, align 8 95 %ap = alloca i8*, align 4 96 %b = alloca double, align 8 97 store double %a, double* %a.addr, align 8 98 %ap1 = bitcast i8** %ap to i8* 99 call void @llvm.va_start(i8* %ap1) 100 %0 = va_arg i8** %ap, double 101 store double %0, double* %b, align 8 102 %ap2 = bitcast i8** %ap to i8* 103 call void @llvm.va_end(i8* %ap2) 104 %tmp = load double* %b, align 8 105 ret double %tmp 106 107 ; CHECK-LABEL: va4: 108 ; CHECK: addiu $sp, $sp, -24 109 ; CHECK: sw $7, 36($sp) 110 ; CHECK: sw $6, 32($sp) 111 ; CHECK: addiu ${{[0-9]+}}, $sp, 32 112 ; CHECK: ldc1 $f0, 32($sp) 113 } 114 115 ; int 116 define i32 @va5(i32 %a, i32 %b, i32 %c, ...) nounwind { 117 entry: 118 %a.addr = alloca i32, align 4 119 %b.addr = alloca i32, align 4 120 %c.addr = alloca i32, align 4 121 %ap = alloca i8*, align 4 122 %d = alloca i32, align 4 123 store i32 %a, i32* %a.addr, align 4 124 store i32 %b, i32* %b.addr, align 4 125 store i32 %c, i32* %c.addr, align 4 126 %ap1 = bitcast i8** %ap to i8* 127 call void @llvm.va_start(i8* %ap1) 128 %0 = va_arg i8** %ap, i32 129 store i32 %0, i32* %d, align 4 130 %ap2 = bitcast i8** %ap to i8* 131 call void @llvm.va_end(i8* %ap2) 132 %tmp = load i32* %d, align 4 133 ret i32 %tmp 134 135 ; CHECK-LABEL: va5: 136 ; CHECK: addiu $sp, $sp, -24 137 ; CHECK: sw $7, 36($sp) 138 ; CHECK: lw $2, 36($sp) 139 } 140 141 ; double 142 define double @va6(i32 %a, i32 %b, i32 %c, ...) nounwind { 143 entry: 144 %a.addr = alloca i32, align 4 145 %b.addr = alloca i32, align 4 146 %c.addr = alloca i32, align 4 147 %ap = alloca i8*, align 4 148 %d = alloca double, align 8 149 store i32 %a, i32* %a.addr, align 4 150 store i32 %b, i32* %b.addr, align 4 151 store i32 %c, i32* %c.addr, align 4 152 %ap1 = bitcast i8** %ap to i8* 153 call void @llvm.va_start(i8* %ap1) 154 %0 = va_arg i8** %ap, double 155 store double %0, double* %d, align 8 156 %ap2 = bitcast i8** %ap to i8* 157 call void @llvm.va_end(i8* %ap2) 158 %tmp = load double* %d, align 8 159 ret double %tmp 160 161 ; CHECK-LABEL: va6: 162 ; CHECK: addiu $sp, $sp, -24 163 ; CHECK: sw $7, 36($sp) 164 ; CHECK: addiu $[[R0:[0-9]+]], $sp, 36 165 ; CHECK: addiu $[[R1:[0-9]+]], $[[R0]], 7 166 ; CHECK: addiu $[[R2:[0-9]+]], $zero, -8 167 ; CHECK: and $[[R3:[0-9]+]], $[[R1]], $[[R2]] 168 ; CHECK: ldc1 $f0, 0($[[R3]]) 169 } 170 171 ; int 172 define i32 @va7(i32 %a, double %b, ...) nounwind { 173 entry: 174 %a.addr = alloca i32, align 4 175 %b.addr = alloca double, align 8 176 %ap = alloca i8*, align 4 177 %c = alloca i32, align 4 178 store i32 %a, i32* %a.addr, align 4 179 store double %b, double* %b.addr, align 8 180 %ap1 = bitcast i8** %ap to i8* 181 call void @llvm.va_start(i8* %ap1) 182 %0 = va_arg i8** %ap, i32 183 store i32 %0, i32* %c, align 4 184 %ap2 = bitcast i8** %ap to i8* 185 call void @llvm.va_end(i8* %ap2) 186 %tmp = load i32* %c, align 4 187 ret i32 %tmp 188 189 ; CHECK-LABEL: va7: 190 ; CHECK: addiu $sp, $sp, -24 191 ; CHECK: lw $2, 40($sp) 192 } 193 194 ; double 195 define double @va8(i32 %a, double %b, ...) nounwind { 196 entry: 197 %a.addr = alloca i32, align 4 198 %b.addr = alloca double, align 8 199 %ap = alloca i8*, align 4 200 %c = alloca double, align 8 201 store i32 %a, i32* %a.addr, align 4 202 store double %b, double* %b.addr, align 8 203 %ap1 = bitcast i8** %ap to i8* 204 call void @llvm.va_start(i8* %ap1) 205 %0 = va_arg i8** %ap, double 206 store double %0, double* %c, align 8 207 %ap2 = bitcast i8** %ap to i8* 208 call void @llvm.va_end(i8* %ap2) 209 %tmp = load double* %c, align 8 210 ret double %tmp 211 212 ; CHECK-LABEL: va8: 213 ; CHECK: addiu $sp, $sp, -32 214 ; CHECK: addiu ${{[0-9]+}}, $sp, 48 215 ; CHECK: ldc1 $f0, 48($sp) 216 } 217 218 ; int 219 define i32 @va9(double %a, double %b, i32 %c, ...) nounwind { 220 entry: 221 %a.addr = alloca double, align 8 222 %b.addr = alloca double, align 8 223 %c.addr = alloca i32, align 4 224 %ap = alloca i8*, align 4 225 %d = alloca i32, align 4 226 store double %a, double* %a.addr, align 8 227 store double %b, double* %b.addr, align 8 228 store i32 %c, i32* %c.addr, align 4 229 %ap1 = bitcast i8** %ap to i8* 230 call void @llvm.va_start(i8* %ap1) 231 %0 = va_arg i8** %ap, i32 232 store i32 %0, i32* %d, align 4 233 %ap2 = bitcast i8** %ap to i8* 234 call void @llvm.va_end(i8* %ap2) 235 %tmp = load i32* %d, align 4 236 ret i32 %tmp 237 238 ; CHECK-LABEL: va9: 239 ; CHECK: addiu $sp, $sp, -32 240 ; CHECK: lw $2, 52($sp) 241 } 242 243 ; double 244 define double @va10(double %a, double %b, i32 %c, ...) nounwind { 245 entry: 246 %a.addr = alloca double, align 8 247 %b.addr = alloca double, align 8 248 %c.addr = alloca i32, align 4 249 %ap = alloca i8*, align 4 250 %d = alloca double, align 8 251 store double %a, double* %a.addr, align 8 252 store double %b, double* %b.addr, align 8 253 store i32 %c, i32* %c.addr, align 4 254 %ap1 = bitcast i8** %ap to i8* 255 call void @llvm.va_start(i8* %ap1) 256 %0 = va_arg i8** %ap, double 257 store double %0, double* %d, align 8 258 %ap2 = bitcast i8** %ap to i8* 259 call void @llvm.va_end(i8* %ap2) 260 %tmp = load double* %d, align 8 261 ret double %tmp 262 263 ; CHECK-LABEL: va10: 264 ; CHECK: addiu $sp, $sp, -32 265 ; CHECK: addiu $[[R0:[0-9]+]], $sp, 52 266 ; CHECK: addiu $[[R1:[0-9]+]], $[[R0]], 7 267 ; CHECK: addiu $[[R2:[0-9]+]], $zero, -8 268 ; CHECK: and $[[R3:[0-9]+]], $[[R1]], $[[R2]] 269 ; CHECK: ldc1 $f0, 0($[[R3]]) 270 } 271