1 // RUN: %clang_cc1 -no-opaque-pointers -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, i32 0, i32 0 } 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 noundef sret(i32*) align 4 dereferenceable(4){{.*}}, float* noalias noundef 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 noundef align 4 dereferenceable(4){{.*}}, float* noalias noundef 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 noundef align 4 dereferenceable(4){{.*}}, float* noalias noundef align 4 dereferenceable(4){{.*}}) 24 25 SWIFTCALL void context_1(CONTEXT void *self) {} 26 // CHECK-LABEL: define {{.*}} void @context_1(i8* noundef swiftself 27 28 SWIFTCALL void context_2(void *arg0, CONTEXT void *self) {} 29 // CHECK-LABEL: define {{.*}} void @context_2(i8*{{.*}}, i8* noundef swiftself 30 31 SWIFTCALL void context_error_1(CONTEXT int *self, ERROR float **error) {} 32 // CHECK-LABEL: define {{.*}} void @context_error_1(i32* noundef swiftself{{.*}}, float** noundef swifterror %0) 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(void) { 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* noundef swiftself [[X]], float** noundef 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* noundef swiftself{{.*}}, float** noundef swifterror %0) 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(void) { \ 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 int f0; 97 int 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: call void @llvm.memset 103 // CHECK: [[CAST:%.*]] = bitcast [[STRUCT1]]* %retval to { i64, i64 }* 104 // CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0 105 // CHECK: [[T0:%.*]] = load i64, i64* [[GEP0]], align 4 106 // CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1 107 // CHECK: [[T1:%.*]] = load i64, i64* [[GEP1]], align 4 108 // CHECK: [[R0:%.*]] = insertvalue { i64, i64 } undef, i64 [[T0]], 0 109 // CHECK: [[R1:%.*]] = insertvalue { i64, i64 } [[R0]], i64 [[T1]], 1 110 // CHECK: ret { i64, i64 } [[R1]] 111 // CHECK: } 112 // CHECK-LABEL: define dso_local swiftcc void @take_struct_1(i64 %0, i64 %1) {{.*}}{ 113 // CHECK: [[V:%.*]] = alloca [[STRUCT1:%.*]], align 4 114 // CHECK: [[CAST:%.*]] = bitcast [[STRUCT1]]* [[V]] to { i64, i64 }* 115 // CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0 116 // CHECK: store i64 %0, i64* [[GEP0]], align 4 117 // CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1 118 // CHECK: store i64 %1, i64* [[GEP1]], align 4 119 // CHECK: ret void 120 // CHECK: } 121 // CHECK-LABEL: define dso_local void @test_struct_1() {{.*}}{ 122 // CHECK: [[AGG:%.*]] = alloca [[STRUCT1:%.*]], align 4 123 // CHECK: [[RET:%.*]] = call swiftcc { i64, i64 } @return_struct_1() 124 // CHECK: [[CAST:%.*]] = bitcast [[STRUCT1]]* [[AGG]] to { i64, i64 }* 125 // CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0 126 // CHECK: [[E0:%.*]] = extractvalue { i64, i64 } [[RET]], 0 127 // CHECK: store i64 [[E0]], i64* [[GEP0]], align 4 128 // CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1 129 // CHECK: [[E1:%.*]] = extractvalue { i64, i64 } [[RET]], 1 130 // CHECK: store i64 [[E1]], i64* [[GEP1]], align 4 131 // CHECK: [[CAST2:%.*]] = bitcast [[STRUCT1]]* [[AGG]] to { i64, i64 }* 132 // CHECK: [[GEP2:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST2]], i32 0, i32 0 133 // CHECK: [[V0:%.*]] = load i64, i64* [[GEP2]], align 4 134 // CHECK: [[GEP3:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST2]], i32 0, i32 1 135 // CHECK: [[V1:%.*]] = load i64, i64* [[GEP3]], align 4 136 // CHECK: call swiftcc void @take_struct_1(i64 [[V0]], i64 [[V1]]) 137 // CHECK: ret void 138 // CHECK: } 139 140 typedef struct { 141 int x; 142 char c0; 143 __attribute__((aligned(2))) char c1; 144 int f0; 145 int f1; 146 } struct_2; 147 TEST(struct_2); 148 // CHECK-LABEL: define dso_local swiftcc { i64, i64 } @return_struct_2() {{.*}}{ 149 // CHECK: [[RET:%.*]] = alloca [[STRUCT2_TYPE]], align 4 150 // CHECK: [[CASTVAR:%.*]] = bitcast {{.*}} [[RET]] 151 // CHECK: call void @llvm.memcpy{{.*}}({{.*}}[[CASTVAR]], {{.*}}[[STRUCT2_RESULT]] 152 // CHECK: [[CAST:%.*]] = bitcast [[STRUCT2_TYPE]]* [[RET]] to { i64, i64 }* 153 // CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0 154 // CHECK: [[T0:%.*]] = load i64, i64* [[GEP0]], align 4 155 // CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1 156 // CHECK: [[T1:%.*]] = load i64, i64* [[GEP1]], align 4 157 // CHECK: [[R0:%.*]] = insertvalue { i64, i64 } undef, i64 [[T0]], 0 158 // CHECK: [[R1:%.*]] = insertvalue { i64, i64 } [[R0]], i64 [[T1]], 1 159 // CHECK: ret { i64, i64 } [[R1]] 160 // CHECK: } 161 // CHECK-LABEL: define dso_local swiftcc void @take_struct_2(i64 %0, i64 %1) {{.*}}{ 162 // CHECK: [[V:%.*]] = alloca [[STRUCT:%.*]], align 4 163 // CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[V]] to { i64, i64 }* 164 // CHECK: [[GEP0:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0 165 // CHECK: store i64 %0, i64* [[GEP0]], align 4 166 // CHECK: [[GEP1:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1 167 // CHECK: store i64 %1, i64* [[GEP1]], align 4 168 // CHECK: ret void 169 // CHECK: } 170 // CHECK-LABEL: define dso_local void @test_struct_2() {{.*}} { 171 // CHECK: [[TMP:%.*]] = alloca [[STRUCT2_TYPE]], align 4 172 // CHECK: [[CALL:%.*]] = call swiftcc { i64, i64 } @return_struct_2() 173 // CHECK: [[CAST_TMP:%.*]] = bitcast [[STRUCT2_TYPE]]* [[TMP]] to { i64, i64 }* 174 // CHECK: [[GEP:%.*]] = getelementptr inbounds {{.*}} [[CAST_TMP]], i32 0, i32 0 175 // CHECK: [[T0:%.*]] = extractvalue { i64, i64 } [[CALL]], 0 176 // CHECK: store i64 [[T0]], i64* [[GEP]], align 4 177 // CHECK: [[GEP:%.*]] = getelementptr inbounds {{.*}} [[CAST_TMP]], i32 0, i32 1 178 // CHECK: [[T0:%.*]] = extractvalue { i64, i64 } [[CALL]], 1 179 // CHECK: store i64 [[T0]], i64* [[GEP]], align 4 180 // CHECK: [[CAST:%.*]] = bitcast [[STRUCT2_TYPE]]* [[TMP]] to { i64, i64 }* 181 // CHECK: [[GEP:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 0 182 // CHECK: [[R0:%.*]] = load i64, i64* [[GEP]], align 4 183 // CHECK: [[GEP:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[CAST]], i32 0, i32 1 184 // CHECK: [[R1:%.*]] = load i64, i64* [[GEP]], align 4 185 // CHECK: call swiftcc void @take_struct_2(i64 [[R0]], i64 [[R1]]) 186 // CHECK: ret void 187 // CHECK: } 188 189 // There's no way to put a field randomly in the middle of an otherwise 190 // empty storage unit in C, so that case has to be tested in C++, which 191 // can use empty structs to introduce arbitrary padding. (In C, they end up 192 // with size 0 and so don't affect layout.) 193 194 // Misaligned data rule. 195 typedef struct { 196 char c0; 197 __attribute__((packed)) float f; 198 } struct_misaligned_1; 199 TEST(struct_misaligned_1) 200 // CHECK-LABEL: define dso_local swiftcc i64 @return_struct_misaligned_1() 201 // CHECK: [[RET:%.*]] = alloca [[STRUCT:%.*]], align 1 202 // CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[RET]] to i8* 203 // CHECK: call void @llvm.memset{{.*}}(i8* align 1 [[CAST]], i8 0, i64 5 204 // CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[RET]] to { i64 }* 205 // CHECK: [[GEP:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[CAST]], i32 0, i32 0 206 // CHECK: [[R0:%.*]] = load i64, i64* [[GEP]], align 1 207 // CHECK: ret i64 [[R0]] 208 // CHECK:} 209 // CHECK-LABEL: define dso_local swiftcc void @take_struct_misaligned_1(i64 %0) {{.*}}{ 210 // CHECK: [[V:%.*]] = alloca [[STRUCT:%.*]], align 1 211 // CHECK: [[CAST:%.*]] = bitcast [[STRUCT]]* [[V]] to { i64 }* 212 // CHECK: [[GEP:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[CAST]], i32 0, i32 0 213 // CHECK: store i64 %0, i64* [[GEP]], align 1 214 // CHECK: ret void 215 // CHECK: } 216 // CHECK: define dso_local void @test_struct_misaligned_1() {{.*}}{ 217 // CHECK: [[AGG:%.*]] = alloca [[STRUCT:%.*]], align 1 218 // CHECK: [[CALL:%.*]] = call swiftcc i64 @return_struct_misaligned_1() 219 // CHECK: [[T0:%.*]] = bitcast [[STRUCT]]* [[AGG]] to { i64 }* 220 // CHECK: [[T1:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[T0]], i32 0, i32 0 221 // CHECK: store i64 [[CALL]], i64* [[T1]], align 1 222 // CHECK: [[T0:%.*]] = bitcast [[STRUCT]]* [[AGG]] to { i64 }* 223 // CHECK: [[T1:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[T0]], i32 0, i32 0 224 // CHECK: [[P:%.*]] = load i64, i64* [[T1]], align 1 225 // CHECK: call swiftcc void @take_struct_misaligned_1(i64 [[P]]) 226 // CHECK: ret void 227 // CHECK: } 228 229 // Too many scalars. 230 typedef struct { 231 long long x[5]; 232 } struct_big_1; 233 TEST(struct_big_1) 234 235 // CHECK-LABEL: define {{.*}} void @return_struct_big_1({{.*}} noalias sret 236 237 // Should not be byval. 238 // CHECK-LABEL: define {{.*}} void @take_struct_big_1({{.*}}* noundef{{( %.*)?}}) 239 240 /*****************************************************************************/ 241 /********************************* TYPE MERGING ******************************/ 242 /*****************************************************************************/ 243 244 typedef union { 245 float f; 246 double d; 247 } union_het_fp; 248 TEST(union_het_fp) 249 // CHECK-LABEL: define dso_local swiftcc i64 @return_union_het_fp() 250 // CHECK: [[RET:%.*]] = alloca [[UNION:%.*]], align 8 251 // CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[RET]] to i8* 252 // CHECK: call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} [[CAST]] 253 // CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[RET]] to { i64 }* 254 // CHECK: [[GEP:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[CAST]], i32 0, i32 0 255 // CHECK: [[R0:%.*]] = load i64, i64* [[GEP]], align 8 256 // CHECK: ret i64 [[R0]] 257 // CHECK-LABEL: define dso_local swiftcc void @take_union_het_fp(i64 %0) {{.*}}{ 258 // CHECK: [[V:%.*]] = alloca [[UNION:%.*]], align 8 259 // CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[V]] to { i64 }* 260 // CHECK: [[GEP:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[CAST]], i32 0, i32 0 261 // CHECK: store i64 %0, i64* [[GEP]], align 8 262 // CHECK: ret void 263 // CHECK: } 264 // CHECK-LABEL: define dso_local void @test_union_het_fp() {{.*}}{ 265 // CHECK: [[AGG:%.*]] = alloca [[UNION:%.*]], align 8 266 // CHECK: [[CALL:%.*]] = call swiftcc i64 @return_union_het_fp() 267 // CHECK: [[T0:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64 }* 268 // CHECK: [[T1:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[T0]], i32 0, i32 0 269 // CHECK: store i64 [[CALL]], i64* [[T1]], align 8 270 // CHECK: [[T0:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64 }* 271 // CHECK: [[T1:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[T0]], i32 0, i32 0 272 // CHECK: [[V0:%.*]] = load i64, i64* [[T1]], align 8 273 // CHECK: call swiftcc void @take_union_het_fp(i64 [[V0]]) 274 // CHECK: ret void 275 // CHECK: } 276 277 278 typedef union { 279 float f1; 280 float f2; 281 } union_hom_fp; 282 TEST(union_hom_fp) 283 // CHECK-LABEL: define dso_local void @test_union_hom_fp() 284 // CHECK: [[TMP:%.*]] = alloca [[REC:%.*]], align 4 285 // CHECK: [[CALL:%.*]] = call [[SWIFTCC]] float @return_union_hom_fp() 286 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG:{ float }]]* 287 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 288 // CHECK: store float [[CALL]], float* [[T0]], align 4 289 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP]] to [[AGG]]* 290 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 291 // CHECK: [[FIRST:%.*]] = load float, float* [[T0]], align 4 292 // CHECK: call [[SWIFTCC]] void @take_union_hom_fp(float [[FIRST]]) 293 // CHECK: ret void 294 295 typedef union { 296 float f1; 297 float4 fv2; 298 } union_hom_fp_partial; 299 TEST(union_hom_fp_partial) 300 // CHECK: define dso_local void @test_union_hom_fp_partial() 301 // CHECK: [[AGG:%.*]] = alloca [[UNION:%.*]], align 16 302 // CHECK: [[CALL:%.*]] = call swiftcc { float, float, float, float } @return_union_hom_fp_partial() 303 // CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { float, float, float, float }* 304 // CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 0 305 // CHECK: [[T1:%.*]] = extractvalue { float, float, float, float } [[CALL]], 0 306 // CHECK: store float [[T1]], float* [[T0]], align 16 307 // CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 1 308 // CHECK: [[T1:%.*]] = extractvalue { float, float, float, float } [[CALL]], 1 309 // CHECK: store float [[T1]], float* [[T0]], align 4 310 // CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 2 311 // CHECK: [[T1:%.*]] = extractvalue { float, float, float, float } [[CALL]], 2 312 // CHECK: store float [[T1]], float* [[T0]], align 8 313 // CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 3 314 // CHECK: [[T1:%.*]] = extractvalue { float, float, float, float } [[CALL]], 3 315 // CHECK: store float [[T1]], float* [[T0]], align 4 316 // CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { float, float, float, float }* 317 // CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 0 318 // CHECK: [[V0:%.*]] = load float, float* [[T0]], align 16 319 // CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 1 320 // CHECK: [[V1:%.*]] = load float, float* [[T0]], align 4 321 // CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 2 322 // CHECK: [[V2:%.*]] = load float, float* [[T0]], align 8 323 // CHECK: [[T0:%.*]] = getelementptr inbounds { float, float, float, float }, { float, float, float, float }* [[CAST]], i32 0, i32 3 324 // CHECK: [[V3:%.*]] = load float, float* [[T0]], align 4 325 // CHECK: call swiftcc void @take_union_hom_fp_partial(float [[V0]], float [[V1]], float [[V2]], float [[V3]]) 326 // CHECK: ret void 327 // CHECK: } 328 329 typedef union { 330 struct { int x, y; } f1; 331 float4 fv2; 332 } union_het_fpv_partial; 333 TEST(union_het_fpv_partial) 334 // CHECK-LABEL: define dso_local void @test_union_het_fpv_partial() 335 // CHECK: [[AGG:%.*]] = alloca [[UNION:%.*]], align 16 336 // CHECK: [[CALL:%.*]] = call swiftcc { i64, float, float } @return_union_het_fpv_partial() 337 // CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, float, float }* 338 // CHECK: [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 0 339 // CHECK: [[T1:%.*]] = extractvalue { i64, float, float } [[CALL]], 0 340 // CHECK: store i64 [[T1]], i64* [[T0]], align 16 341 // CHECK: [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 1 342 // CHECK: [[T1:%.*]] = extractvalue { i64, float, float } [[CALL]], 1 343 // CHECK: store float [[T1]], float* [[T0]], align 8 344 // CHECK: [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 2 345 // CHECK: [[T1:%.*]] = extractvalue { i64, float, float } [[CALL]], 2 346 // CHECK: store float [[T1]], float* [[T0]], align 4 347 // CHECK: [[CAST:%.*]] = bitcast [[UNION]]* [[AGG]] to { i64, float, float }* 348 // CHECK: [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 0 349 // CHECK: [[V0:%.*]] = load i64, i64* [[T0]], align 16 350 // CHECK: [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 1 351 // CHECK: [[V1:%.*]] = load float, float* [[T0]], align 8 352 // CHECK: [[T0:%.*]] = getelementptr inbounds { i64, float, float }, { i64, float, float }* [[CAST]], i32 0, i32 2 353 // CHECK: [[V2:%.*]] = load float, float* [[T0]], align 4 354 // CHECK: call swiftcc void @take_union_het_fpv_partial(i64 [[V0]], float [[V1]], float [[V2]]) 355 // CHECK: ret void 356 // CHECK: } 357 358 /*****************************************************************************/ 359 /****************************** VECTOR LEGALIZATION **************************/ 360 /*****************************************************************************/ 361 362 TEST(int4) 363 // CHECK-LABEL: define {{.*}} <4 x i32> @return_int4() 364 // CHECK-LABEL: define {{.*}} @take_int4(<4 x i32> 365 366 TEST(int8) 367 // CHECK-LABEL: define {{.*}} @return_int8() 368 // CHECK: [[RET:%.*]] = alloca [[REC:<8 x i32>]], align 32 369 // CHECK: [[VAR:%.*]] = alloca [[REC]], align 370 // CHECK: store 371 // CHECK: load 372 // CHECK: store 373 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ <4 x i32>, <4 x i32> }]]* 374 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 375 // CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align 376 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 377 // CHECK: [[SECOND:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align 378 // CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, <4 x i32> }]] undef, <4 x i32> [[FIRST]], 0 379 // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], <4 x i32> [[SECOND]], 1 380 // CHECK: ret [[UAGG]] [[T1]] 381 // CHECK-LABEL: define {{.*}} @take_int8(<4 x i32> noundef %0, <4 x i32> noundef %1) 382 // CHECK: [[V:%.*]] = alloca [[REC]], align 383 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]* 384 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 385 // CHECK: store <4 x i32> %0, <4 x i32>* [[T0]], align 386 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 387 // CHECK: store <4 x i32> %1, <4 x i32>* [[T0]], align 388 // CHECK: ret void 389 // CHECK-LABEL: define dso_local void @test_int8() 390 // CHECK: [[TMP1:%.*]] = alloca [[REC]], align 391 // CHECK: [[TMP2:%.*]] = alloca [[REC]], align 392 // CHECK: [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG]] @return_int8() 393 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP1]] to [[AGG]]* 394 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 395 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0 396 // CHECK: store <4 x i32> [[T1]], <4 x i32>* [[T0]], align 397 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 398 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1 399 // CHECK: store <4 x i32> [[T1]], <4 x i32>* [[T0]], align 400 // CHECK: [[V:%.*]] = load [[REC]], [[REC]]* [[TMP1]], align 401 // CHECK: store [[REC]] [[V]], [[REC]]* [[TMP2]], align 402 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP2]] to [[AGG]]* 403 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 404 // CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align 405 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 406 // CHECK: [[SECOND:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align 407 // CHECK: call [[SWIFTCC]] void @take_int8(<4 x i32> noundef [[FIRST]], <4 x i32> noundef [[SECOND]]) 408 // CHECK: ret void 409 410 TEST(int5) 411 // CHECK-LABEL: define {{.*}} @return_int5() 412 // CHECK: [[RET:%.*]] = alloca [[REC:<5 x i32>]], align 32 413 // CHECK: [[VAR:%.*]] = alloca [[REC]], align 414 // CHECK: store 415 // CHECK: load 416 // CHECK: store 417 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ <4 x i32>, i32 }]]* 418 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 419 // CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align 420 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 421 // CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align 422 // CHECK: [[T0:%.*]] = insertvalue [[UAGG:{ <4 x i32>, i32 }]] undef, <4 x i32> [[FIRST]], 0 423 // CHECK: [[T1:%.*]] = insertvalue [[UAGG]] [[T0]], i32 [[SECOND]], 1 424 // CHECK: ret [[UAGG]] [[T1]] 425 // CHECK-LABEL: define {{.*}} @take_int5(<4 x i32> %0, i32 %1) 426 // CHECK: [[V:%.*]] = alloca [[REC]], align 427 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[V]] to [[AGG]]* 428 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 429 // CHECK: store <4 x i32> %0, <4 x i32>* [[T0]], align 430 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 431 // CHECK: store i32 %1, i32* [[T0]], align 432 // CHECK: ret void 433 // CHECK-LABEL: define dso_local void @test_int5() 434 // CHECK: [[TMP1:%.*]] = alloca [[REC]], align 435 // CHECK: [[TMP2:%.*]] = alloca [[REC]], align 436 // CHECK: [[CALL:%.*]] = call [[SWIFTCC]] [[UAGG]] @return_int5() 437 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP1]] to [[AGG]]* 438 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 439 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 0 440 // CHECK: store <4 x i32> [[T1]], <4 x i32>* [[T0]], align 441 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 442 // CHECK: [[T1:%.*]] = extractvalue [[UAGG]] [[CALL]], 1 443 // CHECK: store i32 [[T1]], i32* [[T0]], align 444 // CHECK: [[V:%.*]] = load [[REC]], [[REC]]* [[TMP1]], align 445 // CHECK: store [[REC]] [[V]], [[REC]]* [[TMP2]], align 446 // CHECK: [[CAST_TMP:%.*]] = bitcast [[REC]]* [[TMP2]] to [[AGG]]* 447 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0 448 // CHECK: [[FIRST:%.*]] = load <4 x i32>, <4 x i32>* [[T0]], align 449 // CHECK: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 1 450 // CHECK: [[SECOND:%.*]] = load i32, i32* [[T0]], align 451 // CHECK: call [[SWIFTCC]] void @take_int5(<4 x i32> [[FIRST]], i32 [[SECOND]]) 452 // CHECK: ret void 453 454 typedef struct { 455 int x; 456 int3 v __attribute__((packed)); 457 } misaligned_int3; 458 TEST(misaligned_int3) 459 // CHECK-LABEL: define dso_local swiftcc void @take_misaligned_int3(i64 %0, i64 %1) 460