1 // RUN: %clang_cc1 -triple x86_64-unknown-windows -emit-llvm -target-cpu core2 -o - %s | FileCheck %s 2 3 #define SWIFTCALL __attribute__((swiftcall)) 4 #define OUT __attribute__((swift_indirect_result)) 5 #define ERROR __attribute__((swift_error_result)) 6 #define CONTEXT __attribute__((swift_context)) 7 8 // CHECK: [[STRUCT2_RESULT:@.*]] = private {{.*}} constant [[STRUCT2_TYPE:%.*]] { i32 0, i8 0, i8 undef, i8 0, float 0.000000e+00, float 0.000000e+00 } 9 10 /*****************************************************************************/ 11 /****************************** PARAMETER ABIS *******************************/ 12 /*****************************************************************************/ 13 14 SWIFTCALL void indirect_result_1(OUT int *arg0, OUT float *arg1) {} 15 // CHECK-LABEL: define {{.*}} void @indirect_result_1(i32* noalias sret align 4 dereferenceable(4){{.*}}, float* noalias align 4 dereferenceable(4){{.*}}) 16 17 // TODO: maybe this shouldn't suppress sret. 18 SWIFTCALL int indirect_result_2(OUT int *arg0, OUT float *arg1) { __builtin_unreachable(); } 19 // CHECK-LABEL: define {{.*}} i32 @indirect_result_2(i32* noalias align 4 dereferenceable(4){{.*}}, float* noalias align 4 dereferenceable(4){{.*}}) 20 21 typedef struct { char array[1024]; } struct_reallybig; 22 SWIFTCALL struct_reallybig indirect_result_3(OUT int *arg0, OUT float *arg1) { __builtin_unreachable(); } 23 // CHECK-LABEL: define {{.*}} void @indirect_result_3({{.*}}* noalias sret {{.*}}, i32* noalias align 4 dereferenceable(4){{.*}}, float* noalias align 4 dereferenceable(4){{.*}}) 24 25 SWIFTCALL void context_1(CONTEXT void *self) {} 26 // CHECK-LABEL: define {{.*}} void @context_1(i8* swiftself 27 28 SWIFTCALL void context_2(void *arg0, CONTEXT void *self) {} 29 // CHECK-LABEL: define {{.*}} void @context_2(i8*{{.*}}, i8* swiftself 30 31 SWIFTCALL void context_error_1(CONTEXT int *self, ERROR float **error) {} 32 // CHECK-LABEL: define {{.*}} void @context_error_1(i32* swiftself{{.*}}, float** swifterror) 33 // CHECK: [[TEMP:%.*]] = alloca float*, align 8 34 // CHECK: [[T0:%.*]] = load float*, float** [[ERRORARG:%.*]], align 8 35 // CHECK: store float* [[T0]], float** [[TEMP]], align 8 36 // CHECK: [[T0:%.*]] = load float*, float** [[TEMP]], align 8 37 // CHECK: store float* [[T0]], float** [[ERRORARG]], align 8 38 void test_context_error_1() { 39 int x; 40 float *error; 41 context_error_1(&x, &error); 42 } 43 // CHECK-LABEL: define dso_local void @test_context_error_1() 44 // CHECK: [[X:%.*]] = alloca i32, align 4 45 // CHECK: [[ERROR:%.*]] = alloca float*, align 8 46 // CHECK: [[TEMP:%.*]] = alloca swifterror float*, align 8 47 // CHECK: [[T0:%.*]] = load float*, float** [[ERROR]], align 8 48 // CHECK: store float* [[T0]], float** [[TEMP]], align 8 49 // CHECK: call [[SWIFTCC:swiftcc]] void @context_error_1(i32* swiftself [[X]], float** swifterror [[TEMP]]) 50 // CHECK: [[T0:%.*]] = load float*, float** [[TEMP]], align 8 51 // CHECK: store float* [[T0]], float** [[ERROR]], align 8 52 53 SWIFTCALL void context_error_2(short s, CONTEXT int *self, ERROR float **error) {} 54 // CHECK-LABEL: define {{.*}} void @context_error_2(i16{{.*}}, i32* swiftself{{.*}}, float** swifterror) 55 56 /*****************************************************************************/ 57 /********************************** LOWERING *********************************/ 58 /*****************************************************************************/ 59 60 typedef float float4 __attribute__((ext_vector_type(4))); 61 typedef float float8 __attribute__((ext_vector_type(8))); 62 typedef double double2 __attribute__((ext_vector_type(2))); 63 typedef double double4 __attribute__((ext_vector_type(4))); 64 typedef int int3 __attribute__((ext_vector_type(3))); 65 typedef int int4 __attribute__((ext_vector_type(4))); 66 typedef int int5 __attribute__((ext_vector_type(5))); 67 typedef int int8 __attribute__((ext_vector_type(8))); 68 69 #define TEST(TYPE) \ 70 SWIFTCALL TYPE return_##TYPE(void) { \ 71 TYPE result = {}; \ 72 return result; \ 73 } \ 74 SWIFTCALL void take_##TYPE(TYPE v) { \ 75 } \ 76 void test_##TYPE() { \ 77 take_##TYPE(return_##TYPE()); \ 78 } 79 80 /*****************************************************************************/ 81 /*********************************** STRUCTS *********************************/ 82 /*****************************************************************************/ 83 84 typedef struct { 85 } struct_empty; 86 TEST(struct_empty); 87 // CHECK-LABEL: define {{.*}} @return_struct_empty() 88 // CHECK: ret void 89 // CHECK-LABEL: define {{.*}} @take_struct_empty() 90 // CHECK: ret void 91 92 typedef struct { 93 int x; 94 char c0; 95 char c1; 96 float f0; 97 float f1; 98 } struct_1; 99 TEST(struct_1); 100 // CHECK-LABEL: define dso_local swiftcc { i64, i64 } @return_struct_1() {{.*}}{ 101 // CHECK: [[RET:%.*]] = alloca [[STRUCT1:%.*]], align 4 102 // CHECK: [[VAR:%.*]] = alloca [[STRUCT1]], align 4 103 // CHECK: call void @llvm.memset 104 // CHECK: call void @llvm.memcpy 105 // CHECK: [[CAST:%.*]] = bitcast [[STRUCT1]]* %retval to { i64, i64 }* 106 // CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0 107 // CHECK: [[T0:%.*]] = load i64, i64* [[GEP0]], align 4 108 // CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1 109 // CHECK: [[T1:%.*]] = load i64, i64* [[GEP1]], align 4 110 // CHECK: [[R0:%.*]] = insertvalue { i64, i64 } undef, i64 [[T0]], 0 111 // CHECK: [[R1:%.*]] = insertvalue { i64, i64 } [[R0]], i64 [[T1]], 1 112 // CHECK: ret { i64, i64 } [[R1]] 113 // CHECK: } 114 // CHECK-LABEL: define dso_local swiftcc void @take_struct_1(i64, i64) {{.*}}{ 115 // CHECK: [[V:%.*]] = alloca [[STRUCT1:%.*]], align 4 116 // CHECK: [[CAST:%.*]] = bitcast [[STRUCT1]]* [[V]] to { i64, i64 }* 117 // CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0 118 // CHECK: store i64 %0, i64* [[GEP0]], align 4 119 // CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1 120 // CHECK: store i64 %1, i64* [[GEP1]], align 4 121 // CHECK: ret void 122 // CHECK: } 123 // CHECK-LABEL: define dso_local void @test_struct_1() {{.*}}{ 124 // CHECK: [[AGG:%.*]] = alloca [[STRUCT1:%.*]], align 4 125 // CHECK: [[RET:%.*]] = call swiftcc { i64, i64 } @return_struct_1() 126 // CHECK: [[CAST:%.*]] = bitcast [[STRUCT1]]* [[AGG]] to { i64, i64 }* 127 // CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0 128 // CHECK: [[E0:%.*]] = extractvalue { i64, i64 } [[RET]], 0 129 // CHECK: store i64 [[E0]], i64* [[GEP0]], align 4 130 // CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1 131 // CHECK: [[E1:%.*]] = extractvalue { i64, i64 } [[RET]], 1 132 // CHECK: store i64 [[E1]], i64* [[GEP1]], align 4 133 // CHECK: [[CAST2:%.*]] = bitcast [[STRUCT1]]* [[AGG]] to { i64, i64 }* 134 // CHECK: [[GEP2:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST2]], i32 0, i32 0 135 // CHECK: [[V0:%.*]] = load i64, i64* [[GEP2]], align 4 136 // CHECK: [[GEP3:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST2]], i32 0, i32 1 137 // CHECK: [[V1:%.*]] = load i64, i64* [[GEP3]], align 4 138 // CHECK: call swiftcc void @take_struct_1(i64 [[V0]], i64 [[V1]]) 139 // CHECK: ret void 140 // CHECK: } 141 142 typedef struct { 143 int x; 144 char c0; 145 __attribute__((aligned(2))) char c1; 146 float f0; 147 float f1; 148 } struct_2; 149 TEST(struct_2); 150 // CHECK-LABEL: define dso_local swiftcc { i64, i64 } @return_struct_2() {{.*}}{ 151 // CHECK: [[RET:%.*]] = alloca [[STRUCT2_TYPE]], align 4 152 // CHECK: [[VAR:%.*]] = alloca [[STRUCT2_TYPE]], align 4 153 // CHECK: [[CASTVAR:%.*]] = bitcast {{.*}} [[VAR]] 154 // CHECK: call void @llvm.memcpy{{.*}}({{.*}}[[CASTVAR]], {{.*}}[[STRUCT2_RESULT]] 155 // CHECK: [[CASTRET:%.*]] = bitcast {{.*}} [[RET]] 156 // CHECK: [[CASTVAR:%.*]] = bitcast {{.*}} [[VAR]] 157 // CHECK: call void @llvm.memcpy{{.*}}({{.*}}[[CASTRET]], {{.*}}[[CASTVAR]] 158 // CHECK: [[CAST:%.*]] = bitcast [[STRUCT2_TYPE]]* [[RET]] to { i64, i64 }* 159 // CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0 160 // CHECK: [[T0:%.*]] = load i64, i64* [[GEP0]], align 4 161 // CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1 162 // CHECK: [[T1:%.*]] = load i64, i64* [[GEP1]], align 4 163 // CHECK: [[R0:%.*]] = insertvalue { i64, i64 } undef, i64 [[T0]], 0 164 // CHECK: [[R1:%.*]] = insertvalue { i64, i64 } [[R0]], i64 [[T1]], 1 165 // CHECK: ret { i64, i64 } [[R1]] 166 // CHECK: } 167 // CHECK-LABEL: define dso_local swiftcc void @take_struct_2(i64, i64) {{.*}}{ 168 // CHECK: [[V:%.*]] = alloca [[STRUCT:%.*]], align 4 169 // CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[V]] to { i64, i64 }* 170 // CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0 171 // CHECK: store i64 %0, i64* [[GEP0]], align 4 172 // CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1 173 // CHECK: store i64 %1, i64* [[GEP1]], align 4 174 // CHECK: ret void 175 // CHECK: } 176 // CHECK-LABEL: define dso_local void @test_struct_2() {{.*}} { 177 // CHECK: [[TMP:%.*]] = alloca [[STRUCT2_TYPE]], align 4 178 // CHECK: [[CALL:%.*]] = call swiftcc { i64, i64 } @return_struct_2() 179 // CHECK: [[CAST_TMP:%.*]] = bitcast [[STRUCT2_TYPE]]* [[TMP]] to { i64, i64 }* 180 // CHECK: [[GEP:%.*]] = getelementptr inbounds {{.*}} [[CAST_TMP]], i32 0, i32 0 181 // CHECK: [[T0:%.*]] = extractvalue { i64, i64 } [[CALL]], 0 182 // CHECK: store i64 [[T0]], i64* [[GEP]], align 4 183 // CHECK: [[GEP:%.*]] = getelementptr inbounds {{.*}} [[CAST_TMP]], i32 0, i32 1 184 // CHECK: [[T0:%.*]] = extractvalue { i64, i64 } [[CALL]], 1 185 // CHECK: store i64 [[T0]], i64* [[GEP]], align 4 186 // CHECK: [[CAST:%.*]] = bitcast [[STRUCT2_TYPE]]* [[TMP]] to { i64, i64 }* 187 // CHECK: [[GEP:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0 188 // CHECK: [[R0:%.*]] = load i64, i64* [[GEP]], align 4 189 // CHECK: [[GEP:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1 190 // CHECK: [[R1:%.*]] = load i64, i64* [[GEP]], align 4 191 // CHECK: call swiftcc void @take_struct_2(i64 [[R0]], i64 [[R1]]) 192 // CHECK: ret void 193 // CHECK: } 194 195 // There's no way to put a field randomly in the middle of an otherwise 196 // empty storage unit in C, so that case has to be tested in C++, which 197 // can use empty structs to introduce arbitrary padding. (In C, they end up 198 // with size 0 and so don't affect layout.) 199 200 // Misaligned data rule. 201 typedef struct { 202 char c0; 203 __attribute__((packed)) float f; 204 } struct_misaligned_1; 205 TEST(struct_misaligned_1) 206 // CHECK-LABEL: define dso_local swiftcc i64 @return_struct_misaligned_1() 207 // CHECK: [[RET:%.*]] = alloca [[STRUCT:%.*]], align 1 208 // CHECK: [[RES:%.*]] = alloca [[STRUCT]], align 1 209 // CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[RES]] to i8* 210 // CHECK: call void @llvm.memset{{.*}}(i8* align 1 [[CAST]], i8 0, i64 5 211 // CHECK: [[CASTRET:%.*]] = bitcast [[STRUCT]]* [[RET]] to i8* 212 // CHECK: [[CASTRES:%.*]] = bitcast [[STRUCT]]* [[RES]] to i8* 213 // CHECK: call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} [[CASTRET]], i8* align {{[0-9]+}} [[CASTRES]], i64 5 214 // CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[RET]] to { i64 }* 215 // CHECK: [[GEP:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[CAST]], i32 0, i32 0 216 // CHECK: [[R0:%.*]] = load i64, i64* [[GEP]], align 1 217 // CHECK: ret i64 [[R0]] 218 // CHECK:} 219 // CHECK-LABEL: define dso_local swiftcc void @take_struct_misaligned_1(i64) {{.*}}{ 220 // CHECK: [[V:%.*]] = alloca [[STRUCT:%.*]], align 1 221 // CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[V]] to { i64 }* 222 // CHECK: [[GEP:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[CAST]], i32 0, i32 0 223 // CHECK: store i64 %0, i64* [[GEP]], align 1 224 // CHECK: ret void 225 // CHECK: } 226 // CHECK: define dso_local void @test_struct_misaligned_1() {{.*}}{ 227 // CHECK: [[AGG:%.*]] = alloca [[STRUCT:%.*]], align 1 228 // CHECK: [[CALL:%.*]] = call swiftcc i64 @return_struct_misaligned_1() 229 // CHECK: [[T0:%.*]] = bitcast [[STRUCT]]* [[AGG]] to { i64 }* 230 // CHECK: [[T1:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[T0]], i32 0, i32 0 231 // CHECK: store i64 [[CALL]], i64* [[T1]], align 1 232 // CHECK: [[T0:%.*]] = bitcast [[STRUCT]]* [[AGG]] to { i64 }* 233 // CHECK: [[T1:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[T0]], i32 0, i32 0 234 // CHECK: [[P:%.*]] = load i64, i64* [[T1]], align 1 235 // CHECK: call swiftcc void @take_struct_misaligned_1(i64 [[P]]) 236 // CHECK: ret void 237 // CHECK: } 238 239 // Too many scalars. 240 typedef struct { 241 long long x[5]; 242 } struct_big_1; 243 TEST(struct_big_1) 244 245 // CHECK-LABEL: define {{.*}} void @return_struct_big_1({{.*}} noalias sret 246 247 // Should not be byval. 248 // CHECK-LABEL: define {{.*}} void @take_struct_big_1({{.*}}*{{( %.*)?}}) 249 250 /*****************************************************************************/ 251 /********************************* TYPE MERGING ******************************/ 252 /*****************************************************************************/ 253 254 typedef union { 255 float f; 256 double d; 257 } union_het_fp; 258 TEST(union_het_fp) 259 // CHECK-LABEL: define dso_local swiftcc i64 @return_union_het_fp() 260 // CHECK: [[RET:%.*]] = alloca [[UNION:%.*]], align 8 261 // CHECK: [[RES:%.*]] = alloca [[UNION]], align 8 262 // CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[RES]] to i8* 263 // CHECK: call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} [[CAST]] 264 // CHECK: [[CASTRET:%.*]] = bitcast [[UNION]]* [[RET]] to i8* 265 // CHECK: [[CASTRES:%.*]] = bitcast [[UNION]]* [[RES]] to i8* 266 // CHECK: call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} [[CASTRET]], i8* align {{[0-9]+}} [[CASTRES]] 267 // CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[RET]] to { i64 }* 268 // CHECK: [[GEP:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[CAST]], i32 0, i32 0 269 // CHECK: [[R0:%.*]] = load i64, i64* [[GEP]], align 8 270 // CHECK: ret i64 [[R0]] 271 // CHECK-LABEL: define dso_local swiftcc void @take_union_het_fp(i64) {{.*}}{ 272 // CHECK: [[V:%.*]] = alloca [[UNION:%.*]], align 8 273 // CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[V]] to { i64 }* 274 // CHECK: [[GEP:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[CAST]], i32 0, i32 0 275 // CHECK: store i64 %0, i64* [[GEP]], align 8 276 // CHECK: ret void 277 // CHECK: } 278 // CHECK-LABEL: define dso_local void @test_union_het_fp() {{.*}}{ 279 // CHECK: [[AGG:%.*]] = alloca [[UNION:%.*]], align 8 280 // CHECK: [[CALL:%.*]] = call swiftcc i64 @return_union_het_fp() 281 // CHECK: [[T0:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64 }* 282 // CHECK: [[T1:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[T0]], i32 0, i32 0 283 // CHECK: store i64 [[CALL]], i64* [[T1]], align 8 284 // CHECK: [[T0:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64 }* 285 // CHECK: [[T1:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[T0]], i32 0, i32 0 286 // CHECK: [[V0:%.*]] = load i64, i64* [[T1]], align 8 287 // CHECK: call swiftcc void @take_union_het_fp(i64 [[V0]]) 288 // CHECK: ret void 289 // CHECK: } 290 291 292 typedef union { 293 float f1; 294 float f2; 295 } union_hom_fp; 296 TEST(union_hom_fp) 297 // CHECK-LABEL: define dso_local void @test_union_hom_fp() 298 // CHECK: [[TMP:%.*]] = alloca [[REC:%.*]], align 4 299 // CHECK: [[CALL:%.*]] = call [[SWIFTCC]] float @return_union_hom_fp() 300 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG:{ float }]]* 301 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 302 // CHECK: store float [[CALL]], float* [[T0]], align 4 303 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG]]* 304 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 305 // CHECK: [[FIRST:%.*]] = load float, float* [[T0]], align 4 306 // CHECK: call [[SWIFTCC]] void @take_union_hom_fp(float [[FIRST]]) 307 // CHECK: ret void 308 309 typedef union { 310 float f1; 311 float4 fv2; 312 } union_hom_fp_partial; 313 TEST(union_hom_fp_partial) 314 // CHECK: define dso_local void @test_union_hom_fp_partial() 315 // CHECK: [[AGG:%.*]] = alloca [[UNION:%.*]], align 16 316 // CHECK: [[CALL:%.*]] = call swiftcc { i64, i64 } @return_union_hom_fp_partial() 317 // CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }* 318 // CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0 319 // CHECK: [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 0 320 // CHECK: store i64 [[T1]], i64* [[T0]], align 16 321 // CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1 322 // CHECK: [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 1 323 // CHECK: store i64 [[T1]], i64* [[T0]], align 8 324 // CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }* 325 // CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0 326 // CHECK: [[V0:%.*]] = load i64, i64* [[T0]], align 16 327 // CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1 328 // CHECK: [[V1:%.*]] = load i64, i64* [[T0]], align 8 329 // CHECK: call swiftcc void @take_union_hom_fp_partial(i64 [[V0]], i64 [[V1]]) 330 // CHECK: ret void 331 // CHECK: } 332 333 typedef union { 334 struct { int x, y; } f1; 335 float4 fv2; 336 } union_het_fpv_partial; 337 TEST(union_het_fpv_partial) 338 // CHECK-LABEL: define dso_local void @test_union_het_fpv_partial() 339 // CHECK: [[AGG:%.*]] = alloca [[UNION:%.*]], align 16 340 // CHECK: [[CALL:%.*]] = call swiftcc { i64, i64 } @return_union_het_fpv_partial() 341 // CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }* 342 // CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0 343 // CHECK: [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 0 344 // CHECK: store i64 [[T1]], i64* [[T0]], align 16 345 // CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1 346 // CHECK: [[T1:%.*]] = extractvalue { i64, i64 } [[CALL]], 1 347 // CHECK: store i64 [[T1]], i64* [[T0]], align 8 348 // CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, i64 }* 349 // CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0 350 // CHECK: [[V0:%.*]] = load i64, i64* [[T0]], align 16 351 // CHECK: [[T0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1 352 // CHECK: [[V1:%.*]] = load i64, i64* [[T0]], align 8 353 // CHECK: call swiftcc void @take_union_het_fpv_partial(i64 [[V0]], i64 [[V1]]) 354 // CHECK: ret void 355 // CHECK: } 356 357 /*****************************************************************************/ 358 /****************************** VECTOR LEGALIZATION **************************/ 359 /*****************************************************************************/ 360 361 TEST(int4) 362 // CHECK-LABEL: define {{.*}} <4 x i32> @return_int4() 363 // CHECK-LABEL: define {{.*}} @take_int4(<4 x i32> 364 365 TEST(int8) 366 // CHECK-LABEL: define {{.*}} @return_int8() 367 // CHECK: [[RET:%.*]] = alloca [[REC:<8 x i32>]], align 32 368 // CHECK: [[VAR:%.*]] = alloca [[REC]], align 369 // CHECK: store 370 // CHECK: load 371 // CHECK: store 372 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ <4 x i32>, <4 x i32> }]]* 373 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 374 // CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align 375 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 376 // CHECK: [[SECOND:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align 377 // CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, <4 x i32> }]] undef, <4 x i32> [[FIRST]], 0 378 // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], <4 x i32> [[SECOND]], 1 379 // CHECK: ret [[UAGG]] [[T1]] 380 // CHECK-LABEL: define {{.*}} @take_int8(<4 x i32>, <4 x i32>) 381 // CHECK: [[V:%.*]] = alloca [[REC]], align 382 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]* 383 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 384 // CHECK: store <4 x i32> %0, <4 x i32>* [[T0]], align 385 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 386 // CHECK: store <4 x i32> %1, <4 x i32>* [[T0]], align 387 // CHECK: ret void 388 // CHECK-LABEL: define dso_local void @test_int8() 389 // CHECK: [[TMP1:%.*]] = alloca [[REC]], align 390 // CHECK: [[TMP2:%.*]] = alloca [[REC]], align 391 // CHECK: [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG]] @return_int8() 392 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP1]] to [[AGG]]* 393 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 394 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0 395 // CHECK: store <4 x i32> [[T1]], <4 x i32>* [[T0]], align 396 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 397 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1 398 // CHECK: store <4 x i32> [[T1]], <4 x i32>* [[T0]], align 399 // CHECK: [[V:%.*]] = load [[REC]], [[REC]]* [[TMP1]], align 400 // CHECK: store [[REC]] [[V]], [[REC]]* [[TMP2]], align 401 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP2]] to [[AGG]]* 402 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 403 // CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align 404 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 405 // CHECK: [[SECOND:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align 406 // CHECK: call [[SWIFTCC]] void @take_int8(<4 x i32> [[FIRST]], <4 x i32> [[SECOND]]) 407 // CHECK: ret void 408 409 TEST(int5) 410 // CHECK-LABEL: define {{.*}} @return_int5() 411 // CHECK: [[RET:%.*]] = alloca [[REC:<5 x i32>]], align 32 412 // CHECK: [[VAR:%.*]] = alloca [[REC]], align 413 // CHECK: store 414 // CHECK: load 415 // CHECK: store 416 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ <4 x i32>, i32 }]]* 417 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 418 // CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align 419 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 420 // CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align 421 // CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, i32 }]] undef, <4 x i32> [[FIRST]], 0 422 // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i32 [[SECOND]], 1 423 // CHECK: ret [[UAGG]] [[T1]] 424 // CHECK-LABEL: define {{.*}} @take_int5(<4 x i32>, i32) 425 // CHECK: [[V:%.*]] = alloca [[REC]], align 426 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]* 427 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 428 // CHECK: store <4 x i32> %0, <4 x i32>* [[T0]], align 429 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 430 // CHECK: store i32 %1, i32* [[T0]], align 431 // CHECK: ret void 432 // CHECK-LABEL: define dso_local void @test_int5() 433 // CHECK: [[TMP1:%.*]] = alloca [[REC]], align 434 // CHECK: [[TMP2:%.*]] = alloca [[REC]], align 435 // CHECK: [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG]] @return_int5() 436 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP1]] to [[AGG]]* 437 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 438 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0 439 // CHECK: store <4 x i32> [[T1]], <4 x i32>* [[T0]], align 440 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 441 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1 442 // CHECK: store i32 [[T1]], i32* [[T0]], align 443 // CHECK: [[V:%.*]] = load [[REC]], [[REC]]* [[TMP1]], align 444 // CHECK: store [[REC]] [[V]], [[REC]]* [[TMP2]], align 445 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP2]] to [[AGG]]* 446 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 447 // CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align 448 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 449 // CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align 450 // CHECK: call [[SWIFTCC]] void @take_int5(<4 x i32> [[FIRST]], i32 [[SECOND]]) 451 // CHECK: ret void 452 453 typedef struct { 454 int x; 455 int3 v __attribute__((packed)); 456 } misaligned_int3; 457 TEST(misaligned_int3) 458 // CHECK-LABEL: define dso_local swiftcc void @take_misaligned_int3(i64, i64) 459