1 // RUN: %clang_cc1 -triple arm64-apple-ios7 -target-abi darwinpcs -emit-llvm -o - %s | FileCheck %s 2 // RUN: %clang_cc1 -triple aarch64-linux-android -emit-llvm -o - %s | FileCheck -check-prefix=ANDROID %s 3 4 #include <stdarg.h> 5 6 typedef __attribute__(( ext_vector_type(2) )) char __char2; 7 typedef __attribute__(( ext_vector_type(3) )) char __char3; 8 typedef __attribute__(( ext_vector_type(4) )) char __char4; 9 typedef __attribute__(( ext_vector_type(5) )) char __char5; 10 typedef __attribute__(( ext_vector_type(9) )) char __char9; 11 typedef __attribute__(( ext_vector_type(19) )) char __char19; 12 typedef __attribute__(( ext_vector_type(3) )) short __short3; 13 typedef __attribute__(( ext_vector_type(5) )) short __short5; 14 typedef __attribute__(( ext_vector_type(3) )) int __int3; 15 typedef __attribute__(( ext_vector_type(5) )) int __int5; 16 typedef __attribute__(( ext_vector_type(3) )) double __double3; 17 18 // Passing legal vector types as varargs. Check that we've allocated the appropriate size 19 double varargs_vec_2c(int fixed, ...) { 20 // ANDROID: varargs_vec_2c 21 // ANDROID: [[VAR:%.*]] = alloca <2 x i8>, align 2 22 // ANDROID: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8 23 // ANDROID: bitcast i8* [[AP_CUR]] to <2 x i8>* 24 va_list ap; 25 double sum = fixed; 26 va_start(ap, fixed); 27 __char2 c3 = va_arg(ap, __char2); 28 sum = sum + c3.x + c3.y; 29 va_end(ap); 30 return sum; 31 } 32 33 double test_2c(__char2 *in) { 34 // ANDROID: call double (i32, ...) @varargs_vec_2c(i32 3, i16 {{%.*}}) 35 return varargs_vec_2c(3, *in); 36 } 37 38 double varargs_vec_3c(int fixed, ...) { 39 // CHECK: varargs_vec_3c 40 // CHECK: alloca <3 x i8>, align 4 41 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8 42 // CHECK: bitcast i8* [[AP_CUR]] to <3 x i8>* 43 va_list ap; 44 double sum = fixed; 45 va_start(ap, fixed); 46 __char3 c3 = va_arg(ap, __char3); 47 sum = sum + c3.x + c3.y; 48 va_end(ap); 49 return sum; 50 } 51 52 double test_3c(__char3 *in) { 53 // CHECK: test_3c 54 // CHECK: call double (i32, ...) @varargs_vec_3c(i32 3, i32 {{%.*}}) 55 return varargs_vec_3c(3, *in); 56 } 57 58 double varargs_vec_4c(int fixed, ...) { 59 // CHECK: varargs_vec_4c 60 // CHECK: alloca <4 x i8>, align 4 61 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8 62 // CHECK: bitcast i8* [[AP_CUR]] to <4 x i8>* 63 va_list ap; 64 double sum = fixed; 65 va_start(ap, fixed); 66 __char4 c4 = va_arg(ap, __char4); 67 sum = sum + c4.x + c4.y; 68 va_end(ap); 69 return sum; 70 } 71 72 double test_4c(__char4 *in) { 73 // CHECK: test_4c 74 // CHECK: call double (i32, ...) @varargs_vec_4c(i32 4, i32 {{%.*}}) 75 return varargs_vec_4c(4, *in); 76 } 77 78 double varargs_vec_5c(int fixed, ...) { 79 // CHECK: varargs_vec_5c 80 // CHECK: alloca <5 x i8>, align 8 81 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8 82 // CHECK: bitcast i8* [[AP_CUR]] to <5 x i8>* 83 va_list ap; 84 double sum = fixed; 85 va_start(ap, fixed); 86 __char5 c5 = va_arg(ap, __char5); 87 sum = sum + c5.x + c5.y; 88 va_end(ap); 89 return sum; 90 } 91 92 double test_5c(__char5 *in) { 93 // CHECK: test_5c 94 // CHECK: call double (i32, ...) @varargs_vec_5c(i32 5, <2 x i32> {{%.*}}) 95 return varargs_vec_5c(5, *in); 96 } 97 98 double varargs_vec_9c(int fixed, ...) { 99 // CHECK: varargs_vec_9c 100 // CHECK: alloca <9 x i8>, align 16 101 // CHECK: [[ALIGN:%.*]] = and i64 {{%.*}}, -16 102 // CHECK: [[AP_ALIGN:%.*]] = inttoptr i64 [[ALIGN]] to i8* 103 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i64 16 104 // CHECK: bitcast i8* [[AP_ALIGN]] to <9 x i8>* 105 va_list ap; 106 double sum = fixed; 107 va_start(ap, fixed); 108 __char9 c9 = va_arg(ap, __char9); 109 sum = sum + c9.x + c9.y; 110 va_end(ap); 111 return sum; 112 } 113 114 double test_9c(__char9 *in) { 115 // CHECK: test_9c 116 // CHECK: call double (i32, ...) @varargs_vec_9c(i32 9, <4 x i32> {{%.*}}) 117 return varargs_vec_9c(9, *in); 118 } 119 120 double varargs_vec_19c(int fixed, ...) { 121 // CHECK: varargs_vec_19c 122 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8 123 // CHECK: [[VAR:%.*]] = bitcast i8* [[AP_CUR]] to <19 x i8>** 124 // CHECK: [[VAR2:%.*]] = load <19 x i8>*, <19 x i8>** [[VAR]] 125 va_list ap; 126 double sum = fixed; 127 va_start(ap, fixed); 128 __char19 c19 = va_arg(ap, __char19); 129 sum = sum + c19.x + c19.y; 130 va_end(ap); 131 return sum; 132 } 133 134 double test_19c(__char19 *in) { 135 // CHECK: test_19c 136 // CHECK: call double (i32, ...) @varargs_vec_19c(i32 19, <19 x i8>* {{%.*}}) 137 return varargs_vec_19c(19, *in); 138 } 139 140 double varargs_vec_3s(int fixed, ...) { 141 // CHECK: varargs_vec_3s 142 // CHECK: alloca <3 x i16>, align 8 143 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8 144 // CHECK: bitcast i8* [[AP_CUR]] to <3 x i16>* 145 va_list ap; 146 double sum = fixed; 147 va_start(ap, fixed); 148 __short3 c3 = va_arg(ap, __short3); 149 sum = sum + c3.x + c3.y; 150 va_end(ap); 151 return sum; 152 } 153 154 double test_3s(__short3 *in) { 155 // CHECK: test_3s 156 // CHECK: call double (i32, ...) @varargs_vec_3s(i32 3, <2 x i32> {{%.*}}) 157 return varargs_vec_3s(3, *in); 158 } 159 160 double varargs_vec_5s(int fixed, ...) { 161 // CHECK: varargs_vec_5s 162 // CHECK: alloca <5 x i16>, align 16 163 // CHECK: [[ALIGN:%.*]] = and i64 {{%.*}}, -16 164 // CHECK: [[AP_ALIGN:%.*]] = inttoptr i64 [[ALIGN]] to i8* 165 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i64 16 166 // CHECK: bitcast i8* [[AP_ALIGN]] to <5 x i16>* 167 va_list ap; 168 double sum = fixed; 169 va_start(ap, fixed); 170 __short5 c5 = va_arg(ap, __short5); 171 sum = sum + c5.x + c5.y; 172 va_end(ap); 173 return sum; 174 } 175 176 double test_5s(__short5 *in) { 177 // CHECK: test_5s 178 // CHECK: call double (i32, ...) @varargs_vec_5s(i32 5, <4 x i32> {{%.*}}) 179 return varargs_vec_5s(5, *in); 180 } 181 182 double varargs_vec_3i(int fixed, ...) { 183 // CHECK: varargs_vec_3i 184 // CHECK: alloca <3 x i32>, align 16 185 // CHECK: [[ALIGN:%.*]] = and i64 {{%.*}}, -16 186 // CHECK: [[AP_ALIGN:%.*]] = inttoptr i64 [[ALIGN]] to i8* 187 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i64 16 188 // CHECK: bitcast i8* [[AP_ALIGN]] to <3 x i32>* 189 va_list ap; 190 double sum = fixed; 191 va_start(ap, fixed); 192 __int3 c3 = va_arg(ap, __int3); 193 sum = sum + c3.x + c3.y; 194 va_end(ap); 195 return sum; 196 } 197 198 double test_3i(__int3 *in) { 199 // CHECK: test_3i 200 // CHECK: call double (i32, ...) @varargs_vec_3i(i32 3, <4 x i32> {{%.*}}) 201 return varargs_vec_3i(3, *in); 202 } 203 204 double varargs_vec_5i(int fixed, ...) { 205 // CHECK: varargs_vec_5i 206 // CHECK: alloca <5 x i32>, align 16 207 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8 208 // CHECK: [[VAR:%.*]] = bitcast i8* [[AP_CUR]] to <5 x i32>** 209 // CHECK: [[VAR2:%.*]] = load <5 x i32>*, <5 x i32>** [[VAR]] 210 va_list ap; 211 double sum = fixed; 212 va_start(ap, fixed); 213 __int5 c5 = va_arg(ap, __int5); 214 sum = sum + c5.x + c5.y; 215 va_end(ap); 216 return sum; 217 } 218 219 double test_5i(__int5 *in) { 220 // CHECK: test_5i 221 // CHECK: call double (i32, ...) @varargs_vec_5i(i32 5, <5 x i32>* {{%.*}}) 222 return varargs_vec_5i(5, *in); 223 } 224 225 double varargs_vec_3d(int fixed, ...) { 226 // CHECK: varargs_vec_3d 227 // CHECK: alloca <3 x double>, align 16 228 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8 229 // CHECK: [[VAR:%.*]] = bitcast i8* [[AP_CUR]] to <3 x double>** 230 // CHECK: [[VAR2:%.*]] = load <3 x double>*, <3 x double>** [[VAR]] 231 va_list ap; 232 double sum = fixed; 233 va_start(ap, fixed); 234 __double3 c3 = va_arg(ap, __double3); 235 sum = sum + c3.x + c3.y; 236 va_end(ap); 237 return sum; 238 } 239 240 double test_3d(__double3 *in) { 241 // CHECK: test_3d 242 // CHECK: call double (i32, ...) @varargs_vec_3d(i32 3, <3 x double>* {{%.*}}) 243 return varargs_vec_3d(3, *in); 244 } 245 246 double varargs_vec(int fixed, ...) { 247 // CHECK: varargs_vec 248 va_list ap; 249 double sum = fixed; 250 va_start(ap, fixed); 251 __char3 c3 = va_arg(ap, __char3); 252 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8 253 // CHECK: bitcast i8* [[AP_CUR]] to <3 x i8>* 254 sum = sum + c3.x + c3.y; 255 __char5 c5 = va_arg(ap, __char5); 256 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8 257 // CHECK: bitcast i8* [[AP_CUR]] to <5 x i8>* 258 sum = sum + c5.x + c5.y; 259 __char9 c9 = va_arg(ap, __char9); 260 // CHECK: [[ALIGN:%.*]] = and i64 {{%.*}}, -16 261 // CHECK: [[AP_ALIGN:%.*]] = inttoptr i64 [[ALIGN]] to i8* 262 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i64 16 263 // CHECK: bitcast i8* [[AP_ALIGN]] to <9 x i8>* 264 sum = sum + c9.x + c9.y; 265 __char19 c19 = va_arg(ap, __char19); 266 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8 267 // CHECK: [[VAR:%.*]] = bitcast i8* [[AP_CUR]] to <19 x i8>** 268 // CHECK: [[VAR2:%.*]] = load <19 x i8>*, <19 x i8>** [[VAR]] 269 sum = sum + c19.x + c19.y; 270 __short3 s3 = va_arg(ap, __short3); 271 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8 272 // CHECK: bitcast i8* [[AP_CUR]] to <3 x i16>* 273 sum = sum + s3.x + s3.y; 274 __short5 s5 = va_arg(ap, __short5); 275 // CHECK: [[ALIGN:%.*]] = and i64 {{%.*}}, -16 276 // CHECK: [[AP_ALIGN:%.*]] = inttoptr i64 [[ALIGN]] to i8* 277 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i64 16 278 // CHECK: bitcast i8* [[AP_ALIGN]] to <5 x i16>* 279 sum = sum + s5.x + s5.y; 280 __int3 i3 = va_arg(ap, __int3); 281 // CHECK: [[ALIGN:%.*]] = and i64 {{%.*}}, -16 282 // CHECK: [[AP_ALIGN:%.*]] = inttoptr i64 [[ALIGN]] to i8* 283 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_ALIGN]], i64 16 284 // CHECK: bitcast i8* [[AP_ALIGN]] to <3 x i32>* 285 sum = sum + i3.x + i3.y; 286 __int5 i5 = va_arg(ap, __int5); 287 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8 288 // CHECK: [[VAR:%.*]] = bitcast i8* [[AP_CUR]] to <5 x i32>** 289 // CHECK: [[VAR2:%.*]] = load <5 x i32>*, <5 x i32>** [[VAR]] 290 sum = sum + i5.x + i5.y; 291 __double3 d3 = va_arg(ap, __double3); 292 // CHECK: [[AP_NEXT:%.*]] = getelementptr inbounds i8, i8* [[AP_CUR:%.*]], i64 8 293 // CHECK: [[VAR:%.*]] = bitcast i8* [[AP_CUR]] to <3 x double>** 294 // CHECK: [[VAR2:%.*]] = load <3 x double>*, <3 x double>** [[VAR]] 295 sum = sum + d3.x + d3.y; 296 va_end(ap); 297 return sum; 298 } 299 300 double test(__char3 *c3, __char5 *c5, __char9 *c9, __char19 *c19, 301 __short3 *s3, __short5 *s5, __int3 *i3, __int5 *i5, 302 __double3 *d3) { 303 double ret = varargs_vec(3, *c3, *c5, *c9, *c19, *s3, *s5, *i3, *i5, *d3); 304 // CHECK: call double (i32, ...) @varargs_vec(i32 3, i32 {{%.*}}, <2 x i32> {{%.*}}, <4 x i32> {{%.*}}, <19 x i8>* {{%.*}}, <2 x i32> {{%.*}}, <4 x i32> {{%.*}}, <4 x i32> {{%.*}}, <5 x i32>* {{%.*}}, <3 x double>* {{%.*}}) 305 return ret; 306 } 307 308 __attribute__((noinline)) double args_vec_3c(int fixed, __char3 c3) { 309 // CHECK: args_vec_3c 310 // CHECK: [[C3:%.*]] = alloca <3 x i8>, align 4 311 // CHECK: [[TMP:%.*]] = bitcast <3 x i8>* [[C3]] to i32* 312 // CHECK: store i32 {{%.*}}, i32* [[TMP]] 313 double sum = fixed; 314 sum = sum + c3.x + c3.y; 315 return sum; 316 } 317 318 double fixed_3c(__char3 *in) { 319 // CHECK: fixed_3c 320 // CHECK: call double @args_vec_3c(i32 3, i32 {{%.*}}) 321 return args_vec_3c(3, *in); 322 } 323 324 __attribute__((noinline)) double args_vec_5c(int fixed, __char5 c5) { 325 // CHECK: args_vec_5c 326 // CHECK: [[C5:%.*]] = alloca <5 x i8>, align 8 327 // CHECK: [[TMP:%.*]] = bitcast <5 x i8>* [[C5]] to <2 x i32>* 328 // CHECK: store <2 x i32> {{%.*}}, <2 x i32>* [[TMP]], align 8 329 double sum = fixed; 330 sum = sum + c5.x + c5.y; 331 return sum; 332 } 333 334 double fixed_5c(__char5 *in) { 335 // CHECK: fixed_5c 336 // CHECK: call double @args_vec_5c(i32 5, <2 x i32> {{%.*}}) 337 return args_vec_5c(5, *in); 338 } 339 340 __attribute__((noinline)) double args_vec_9c(int fixed, __char9 c9) { 341 // CHECK: args_vec_9c 342 // CHECK: [[C9:%.*]] = alloca <9 x i8>, align 16 343 // CHECK: [[TMP:%.*]] = bitcast <9 x i8>* [[C9]] to <4 x i32>* 344 // CHECK: store <4 x i32> {{%.*}}, <4 x i32>* [[TMP]], align 16 345 double sum = fixed; 346 sum = sum + c9.x + c9.y; 347 return sum; 348 } 349 350 double fixed_9c(__char9 *in) { 351 // CHECK: fixed_9c 352 // CHECK: call double @args_vec_9c(i32 9, <4 x i32> {{%.*}}) 353 return args_vec_9c(9, *in); 354 } 355 356 __attribute__((noinline)) double args_vec_19c(int fixed, __char19 c19) { 357 // CHECK: args_vec_19c 358 // CHECK: [[C19:%.*]] = load <19 x i8>, <19 x i8>* {{.*}}, align 16 359 double sum = fixed; 360 sum = sum + c19.x + c19.y; 361 return sum; 362 } 363 364 double fixed_19c(__char19 *in) { 365 // CHECK: fixed_19c 366 // CHECK: call double @args_vec_19c(i32 19, <19 x i8>* {{%.*}}) 367 return args_vec_19c(19, *in); 368 } 369 370 __attribute__((noinline)) double args_vec_3s(int fixed, __short3 c3) { 371 // CHECK: args_vec_3s 372 // CHECK: [[C3:%.*]] = alloca <3 x i16>, align 8 373 // CHECK: [[TMP:%.*]] = bitcast <3 x i16>* [[C3]] to <2 x i32>* 374 // CHECK: store <2 x i32> {{%.*}}, <2 x i32>* [[TMP]], align 8 375 double sum = fixed; 376 sum = sum + c3.x + c3.y; 377 return sum; 378 } 379 380 double fixed_3s(__short3 *in) { 381 // CHECK: fixed_3s 382 // CHECK: call double @args_vec_3s(i32 3, <2 x i32> {{%.*}}) 383 return args_vec_3s(3, *in); 384 } 385 386 __attribute__((noinline)) double args_vec_5s(int fixed, __short5 c5) { 387 // CHECK: args_vec_5s 388 // CHECK: [[C5:%.*]] = alloca <5 x i16>, align 16 389 // CHECK: [[TMP:%.*]] = bitcast <5 x i16>* [[C5]] to <4 x i32>* 390 // CHECK: store <4 x i32> {{%.*}}, <4 x i32>* [[TMP]], align 16 391 double sum = fixed; 392 sum = sum + c5.x + c5.y; 393 return sum; 394 } 395 396 double fixed_5s(__short5 *in) { 397 // CHECK: fixed_5s 398 // CHECK: call double @args_vec_5s(i32 5, <4 x i32> {{%.*}}) 399 return args_vec_5s(5, *in); 400 } 401 402 __attribute__((noinline)) double args_vec_3i(int fixed, __int3 c3) { 403 // CHECK: args_vec_3i 404 // CHECK: [[C3:%.*]] = alloca <3 x i32>, align 16 405 // CHECK: [[TMP:%.*]] = bitcast <3 x i32>* [[C3]] to <4 x i32>* 406 // CHECK: store <4 x i32> {{%.*}}, <4 x i32>* [[TMP]], align 16 407 double sum = fixed; 408 sum = sum + c3.x + c3.y; 409 return sum; 410 } 411 412 double fixed_3i(__int3 *in) { 413 // CHECK: fixed_3i 414 // CHECK: call double @args_vec_3i(i32 3, <4 x i32> {{%.*}}) 415 return args_vec_3i(3, *in); 416 } 417 418 __attribute__((noinline)) double args_vec_5i(int fixed, __int5 c5) { 419 // CHECK: args_vec_5i 420 // CHECK: [[C5:%.*]] = load <5 x i32>, <5 x i32>* {{%.*}}, align 16 421 double sum = fixed; 422 sum = sum + c5.x + c5.y; 423 return sum; 424 } 425 426 double fixed_5i(__int5 *in) { 427 // CHECK: fixed_5i 428 // CHECK: call double @args_vec_5i(i32 5, <5 x i32>* {{%.*}}) 429 return args_vec_5i(5, *in); 430 } 431 432 __attribute__((noinline)) double args_vec_3d(int fixed, __double3 c3) { 433 // CHECK: args_vec_3d 434 // CHECK: [[CAST:%.*]] = bitcast <3 x double>* {{%.*}} to <4 x double>* 435 // CHECK: [[LOAD:%.*]] = load <4 x double>, <4 x double>* [[CAST]] 436 // CHECK: shufflevector <4 x double> [[LOAD]], <4 x double> undef, <3 x i32> <i32 0, i32 1, i32 2> 437 double sum = fixed; 438 sum = sum + c3.x + c3.y; 439 return sum; 440 } 441 442 double fixed_3d(__double3 *in) { 443 // CHECK: fixed_3d 444 // CHECK: call double @args_vec_3d(i32 3, <3 x double>* {{%.*}}) 445 return args_vec_3d(3, *in); 446 } 447