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