xref: /llvm-project/llvm/test/CodeGen/WebAssembly/expand-variadic-call.ll (revision 94473f4db6a6f5f12d7c4081455b5b596094eac5)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: -p --function-signature
2; RUN: opt -S --passes=expand-variadics --expand-variadics-override=lowering < %s | FileCheck %s
3; REQUIRES: webassembly-registered-target
4target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
5target triple = "wasm32-unknown-unknown"
6
7; Check the variables are lowered to the locations this target expects
8
9; The types show the call frames
10; CHECK: %single_i32.vararg = type <{ i32 }>
11; CHECK: %single_double.vararg = type <{ double }>
12; CHECK: %single_v4f32.vararg = type <{ <4 x float> }>
13; CHECK: %single_v8f32.vararg = type <{ <8 x float> }>
14; CHECK: %single_v16f32.vararg = type <{ <16 x float> }>
15; CHECK: %single_v32f32.vararg = type <{ <32 x float> }>
16; CHECK: %i32_double.vararg = type <{ i32, [4 x i8], double }>
17; CHECK: %double_i32.vararg = type <{ double, i32 }>
18; CHECK: %i32_libcS.vararg = type <{ i32, ptr }>
19; CHECK: %libcS_i32.vararg = type <{ ptr, i32 }>
20; CHECK: %i32_v4f32.vararg = type <{ i32, [12 x i8], <4 x float> }>
21; CHECK: %v4f32_i32.vararg = type <{ <4 x float>, i32 }>
22; CHECK: %i32_v8f32.vararg = type <{ i32, [28 x i8], <8 x float> }>
23; CHECK: %v8f32_i32.vararg = type <{ <8 x float>, i32 }>
24; CHECK: %i32_v16f32.vararg = type <{ i32, [60 x i8], <16 x float> }>
25; CHECK: %v16f32_i32.vararg = type <{ <16 x float>, i32 }>
26; CHECK: %i32_v32f32.vararg = type <{ i32, [124 x i8], <32 x float> }>
27; CHECK: %v32f32_i32.vararg = type <{ <32 x float>, i32 }>
28; CHECK: %fptr_single_i32.vararg = type <{ i32 }>
29; CHECK: %fptr_libcS.vararg = type <{ ptr }>
30
31%struct.libcS = type { i8, i16, i32, i32, float, double }
32
33@vararg_ptr = hidden global ptr @vararg, align 4
34
35define hidden void @copy(ptr noundef %va) {
36; CHECK-LABEL: define {{[^@]+}}@copy(ptr noundef %va) {
37; CHECK-NEXT:  entry:
38; CHECK-NEXT:    %va.addr = alloca ptr, align 4
39; CHECK-NEXT:    %cp = alloca ptr, align 4
40; CHECK-NEXT:    store ptr %va, ptr %va.addr, align 4
41; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %cp)
42; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr %cp, ptr %va.addr, i32 4, i1 false)
43; CHECK-NEXT:    %0 = load ptr, ptr %cp, align 4
44; CHECK-NEXT:    call void @valist(ptr noundef %0)
45; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %cp)
46; CHECK-NEXT:    ret void
47;
48entry:
49  %va.addr = alloca ptr, align 4
50  %cp = alloca ptr, align 4
51  store ptr %va, ptr %va.addr, align 4
52  call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %cp)
53  call void @llvm.va_copy.p0(ptr nonnull %cp, ptr nonnull %va.addr)
54  %0 = load ptr, ptr %cp, align 4
55  call void @valist(ptr noundef %0)
56  call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %cp)
57  ret void
58}
59
60declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture)
61
62declare void @llvm.va_copy.p0(ptr, ptr)
63
64declare void @valist(ptr noundef)
65
66declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture)
67
68define hidden void @start_once(...) {
69; CHECK-LABEL: define {{[^@]+}}@start_once(ptr %varargs) {
70; CHECK-NEXT:  entry:
71; CHECK-NEXT:    %s = alloca ptr, align 4
72; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %s)
73; CHECK-NEXT:    store ptr %varargs, ptr %s, align 4
74; CHECK-NEXT:    %0 = load ptr, ptr %s, align 4
75; CHECK-NEXT:    call void @valist(ptr noundef %0)
76; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %s)
77; CHECK-NEXT:    ret void
78;
79entry:
80  %s = alloca ptr, align 4
81  call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %s)
82  call void @llvm.va_start.p0(ptr nonnull %s)
83  %0 = load ptr, ptr %s, align 4
84  call void @valist(ptr noundef %0)
85  call void @llvm.va_end.p0(ptr %s)
86  call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %s)
87  ret void
88}
89
90declare void @llvm.va_start.p0(ptr)
91
92declare void @llvm.va_end.p0(ptr)
93
94define hidden void @start_twice(...) {
95; CHECK-LABEL: define {{[^@]+}}@start_twice(ptr %varargs) {
96; CHECK-NEXT:  entry:
97; CHECK-NEXT:    %s0 = alloca ptr, align 4
98; CHECK-NEXT:    %s1 = alloca ptr, align 4
99; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %s0)
100; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %s1)
101; CHECK-NEXT:    store ptr %varargs, ptr %s0, align 4
102; CHECK-NEXT:    %0 = load ptr, ptr %s0, align 4
103; CHECK-NEXT:    call void @valist(ptr noundef %0)
104; CHECK-NEXT:    store ptr %varargs, ptr %s1, align 4
105; CHECK-NEXT:    %1 = load ptr, ptr %s1, align 4
106; CHECK-NEXT:    call void @valist(ptr noundef %1)
107; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %s1)
108; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %s0)
109; CHECK-NEXT:    ret void
110;
111entry:
112  %s0 = alloca ptr, align 4
113  %s1 = alloca ptr, align 4
114  call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %s0)
115  call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %s1)
116  call void @llvm.va_start.p0(ptr nonnull %s0)
117  %0 = load ptr, ptr %s0, align 4
118  call void @valist(ptr noundef %0)
119  call void @llvm.va_end.p0(ptr %s0)
120  call void @llvm.va_start.p0(ptr nonnull %s1)
121  %1 = load ptr, ptr %s1, align 4
122  call void @valist(ptr noundef %1)
123  call void @llvm.va_end.p0(ptr %s1)
124  call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %s1)
125  call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %s0)
126  ret void
127}
128
129define hidden void @single_i32(i32 noundef %x) {
130; CHECK-LABEL: define {{[^@]+}}@single_i32(i32 noundef %x) {
131; CHECK-NEXT:  entry:
132; CHECK-NEXT:    %vararg_buffer = alloca %single_i32.vararg, align 16
133; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr %vararg_buffer)
134; CHECK-NEXT:    %0 = getelementptr inbounds nuw %single_i32.vararg, ptr %vararg_buffer, i32 0, i32 0
135; CHECK-NEXT:    store i32 %x, ptr %0, align 4
136; CHECK-NEXT:    call void @vararg(ptr %vararg_buffer)
137; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr %vararg_buffer)
138; CHECK-NEXT:    ret void
139;
140entry:
141  tail call void (...) @vararg(i32 noundef %x)
142  ret void
143}
144
145declare void @vararg(...)
146
147define hidden void @single_double(double noundef %x) {
148; CHECK-LABEL: define {{[^@]+}}@single_double(double noundef %x) {
149; CHECK-NEXT:  entry:
150; CHECK-NEXT:    %vararg_buffer = alloca %single_double.vararg, align 16
151; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 8, ptr %vararg_buffer)
152; CHECK-NEXT:    %0 = getelementptr inbounds nuw %single_double.vararg, ptr %vararg_buffer, i32 0, i32 0
153; CHECK-NEXT:    store double %x, ptr %0, align 8
154; CHECK-NEXT:    call void @vararg(ptr %vararg_buffer)
155; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 8, ptr %vararg_buffer)
156; CHECK-NEXT:    ret void
157;
158entry:
159  tail call void (...) @vararg(double noundef %x)
160  ret void
161}
162
163define hidden void @single_v4f32(<4 x float> noundef %x) {
164; CHECK-LABEL: define {{[^@]+}}@single_v4f32(<4 x float> noundef %x) {
165; CHECK-NEXT:  entry:
166; CHECK-NEXT:    %vararg_buffer = alloca %single_v4f32.vararg, align 16
167; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 16, ptr %vararg_buffer)
168; CHECK-NEXT:    %0 = getelementptr inbounds nuw %single_v4f32.vararg, ptr %vararg_buffer, i32 0, i32 0
169; CHECK-NEXT:    store <4 x float> %x, ptr %0, align 16
170; CHECK-NEXT:    call void @vararg(ptr %vararg_buffer)
171; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 16, ptr %vararg_buffer)
172; CHECK-NEXT:    ret void
173;
174entry:
175  tail call void (...) @vararg(<4 x float> noundef %x)
176  ret void
177}
178
179define hidden void @single_v8f32(<8 x float> noundef %x) {
180; CHECK-LABEL: define {{[^@]+}}@single_v8f32(<8 x float> noundef %x) {
181; CHECK-NEXT:  entry:
182; CHECK-NEXT:    %vararg_buffer = alloca %single_v8f32.vararg, align 32
183; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 32, ptr %vararg_buffer)
184; CHECK-NEXT:    %0 = getelementptr inbounds nuw %single_v8f32.vararg, ptr %vararg_buffer, i32 0, i32 0
185; CHECK-NEXT:    store <8 x float> %x, ptr %0, align 32
186; CHECK-NEXT:    call void @vararg(ptr %vararg_buffer)
187; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 32, ptr %vararg_buffer)
188; CHECK-NEXT:    ret void
189;
190entry:
191  tail call void (...) @vararg(<8 x float> noundef %x)
192  ret void
193}
194
195define hidden void @single_v16f32(<16 x float> noundef %x) {
196; CHECK-LABEL: define {{[^@]+}}@single_v16f32(<16 x float> noundef %x) {
197; CHECK-NEXT:  entry:
198; CHECK-NEXT:    %vararg_buffer = alloca %single_v16f32.vararg, align 64
199; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 64, ptr %vararg_buffer)
200; CHECK-NEXT:    %0 = getelementptr inbounds nuw %single_v16f32.vararg, ptr %vararg_buffer, i32 0, i32 0
201; CHECK-NEXT:    store <16 x float> %x, ptr %0, align 64
202; CHECK-NEXT:    call void @vararg(ptr %vararg_buffer)
203; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 64, ptr %vararg_buffer)
204; CHECK-NEXT:    ret void
205;
206entry:
207  tail call void (...) @vararg(<16 x float> noundef %x)
208  ret void
209}
210
211define hidden void @single_v32f32(<32 x float> noundef %x) {
212; CHECK-LABEL: define {{[^@]+}}@single_v32f32(<32 x float> noundef %x) {
213; CHECK-NEXT:  entry:
214; CHECK-NEXT:    %vararg_buffer = alloca %single_v32f32.vararg, align 128
215; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 128, ptr %vararg_buffer)
216; CHECK-NEXT:    %0 = getelementptr inbounds nuw %single_v32f32.vararg, ptr %vararg_buffer, i32 0, i32 0
217; CHECK-NEXT:    store <32 x float> %x, ptr %0, align 128
218; CHECK-NEXT:    call void @vararg(ptr %vararg_buffer)
219; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 128, ptr %vararg_buffer)
220; CHECK-NEXT:    ret void
221;
222entry:
223  tail call void (...) @vararg(<32 x float> noundef %x)
224  ret void
225}
226
227define hidden void @i32_double(i32 noundef %x, double noundef %y) {
228; CHECK-LABEL: define {{[^@]+}}@i32_double(i32 noundef %x, double noundef %y) {
229; CHECK-NEXT:  entry:
230; CHECK-NEXT:    %vararg_buffer = alloca %i32_double.vararg, align 16
231; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 16, ptr %vararg_buffer)
232; CHECK-NEXT:    %0 = getelementptr inbounds nuw %i32_double.vararg, ptr %vararg_buffer, i32 0, i32 0
233; CHECK-NEXT:    store i32 %x, ptr %0, align 4
234; CHECK-NEXT:    %1 = getelementptr inbounds nuw %i32_double.vararg, ptr %vararg_buffer, i32 0, i32 2
235; CHECK-NEXT:    store double %y, ptr %1, align 8
236; CHECK-NEXT:    call void @vararg(ptr %vararg_buffer)
237; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 16, ptr %vararg_buffer)
238; CHECK-NEXT:    ret void
239;
240entry:
241  tail call void (...) @vararg(i32 noundef %x, double noundef %y)
242  ret void
243}
244
245define hidden void @double_i32(double noundef %x, i32 noundef %y) {
246; CHECK-LABEL: define {{[^@]+}}@double_i32(double noundef %x, i32 noundef %y) {
247; CHECK-NEXT:  entry:
248; CHECK-NEXT:    %vararg_buffer = alloca %double_i32.vararg, align 16
249; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 12, ptr %vararg_buffer)
250; CHECK-NEXT:    %0 = getelementptr inbounds nuw %double_i32.vararg, ptr %vararg_buffer, i32 0, i32 0
251; CHECK-NEXT:    store double %x, ptr %0, align 8
252; CHECK-NEXT:    %1 = getelementptr inbounds nuw %double_i32.vararg, ptr %vararg_buffer, i32 0, i32 1
253; CHECK-NEXT:    store i32 %y, ptr %1, align 4
254; CHECK-NEXT:    call void @vararg(ptr %vararg_buffer)
255; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 12, ptr %vararg_buffer)
256; CHECK-NEXT:    ret void
257;
258entry:
259  tail call void (...) @vararg(double noundef %x, i32 noundef %y)
260  ret void
261}
262
263define hidden void @i32_libcS(i32 noundef %x, ptr noundef byval(%struct.libcS) align 8 %y) {
264; CHECK-LABEL: define {{[^@]+}}@i32_libcS(i32 noundef %x, ptr noundef byval(%struct.libcS) align 8 %y) {
265; CHECK-NEXT:  entry:
266; CHECK-NEXT:    %IndirectAlloca = alloca %struct.libcS, align 8
267; CHECK-NEXT:    %vararg_buffer = alloca %i32_libcS.vararg, align 16
268; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr %IndirectAlloca, ptr %y, i64 24, i1 false)
269; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 8, ptr %vararg_buffer)
270; CHECK-NEXT:    %0 = getelementptr inbounds nuw %i32_libcS.vararg, ptr %vararg_buffer, i32 0, i32 0
271; CHECK-NEXT:    store i32 %x, ptr %0, align 4
272; CHECK-NEXT:    %1 = getelementptr inbounds nuw %i32_libcS.vararg, ptr %vararg_buffer, i32 0, i32 1
273; CHECK-NEXT:    store ptr %IndirectAlloca, ptr %1, align 4
274; CHECK-NEXT:    call void @vararg(ptr %vararg_buffer)
275; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 8, ptr %vararg_buffer)
276; CHECK-NEXT:    ret void
277;
278entry:
279  tail call void (...) @vararg(i32 noundef %x, ptr noundef nonnull byval(%struct.libcS) align 8 %y)
280  ret void
281}
282
283define hidden void @libcS_i32(ptr noundef byval(%struct.libcS) align 8 %x, i32 noundef %y) {
284; CHECK-LABEL: define {{[^@]+}}@libcS_i32(ptr noundef byval(%struct.libcS) align 8 %x, i32 noundef %y) {
285; CHECK-NEXT:  entry:
286; CHECK-NEXT:    %IndirectAlloca = alloca %struct.libcS, align 8
287; CHECK-NEXT:    %vararg_buffer = alloca %libcS_i32.vararg, align 16
288; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr %IndirectAlloca, ptr %x, i64 24, i1 false)
289; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 8, ptr %vararg_buffer)
290; CHECK-NEXT:    %0 = getelementptr inbounds nuw %libcS_i32.vararg, ptr %vararg_buffer, i32 0, i32 0
291; CHECK-NEXT:    store ptr %IndirectAlloca, ptr %0, align 4
292; CHECK-NEXT:    %1 = getelementptr inbounds nuw %libcS_i32.vararg, ptr %vararg_buffer, i32 0, i32 1
293; CHECK-NEXT:    store i32 %y, ptr %1, align 4
294; CHECK-NEXT:    call void @vararg(ptr %vararg_buffer)
295; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 8, ptr %vararg_buffer)
296; CHECK-NEXT:    ret void
297;
298entry:
299  tail call void (...) @vararg(ptr noundef nonnull byval(%struct.libcS) align 8 %x, i32 noundef %y)
300  ret void
301}
302
303define hidden void @i32_v4f32(i32 noundef %x, <4 x float> noundef %y) {
304; CHECK-LABEL: define {{[^@]+}}@i32_v4f32(i32 noundef %x, <4 x float> noundef %y) {
305; CHECK-NEXT:  entry:
306; CHECK-NEXT:    %vararg_buffer = alloca %i32_v4f32.vararg, align 16
307; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 32, ptr %vararg_buffer)
308; CHECK-NEXT:    %0 = getelementptr inbounds nuw %i32_v4f32.vararg, ptr %vararg_buffer, i32 0, i32 0
309; CHECK-NEXT:    store i32 %x, ptr %0, align 4
310; CHECK-NEXT:    %1 = getelementptr inbounds nuw %i32_v4f32.vararg, ptr %vararg_buffer, i32 0, i32 2
311; CHECK-NEXT:    store <4 x float> %y, ptr %1, align 16
312; CHECK-NEXT:    call void @vararg(ptr %vararg_buffer)
313; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 32, ptr %vararg_buffer)
314; CHECK-NEXT:    ret void
315;
316entry:
317  tail call void (...) @vararg(i32 noundef %x, <4 x float> noundef %y)
318  ret void
319}
320
321define hidden void @v4f32_i32(<4 x float> noundef %x, i32 noundef %y) {
322; CHECK-LABEL: define {{[^@]+}}@v4f32_i32(<4 x float> noundef %x, i32 noundef %y) {
323; CHECK-NEXT:  entry:
324; CHECK-NEXT:    %vararg_buffer = alloca %v4f32_i32.vararg, align 16
325; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 20, ptr %vararg_buffer)
326; CHECK-NEXT:    %0 = getelementptr inbounds nuw %v4f32_i32.vararg, ptr %vararg_buffer, i32 0, i32 0
327; CHECK-NEXT:    store <4 x float> %x, ptr %0, align 16
328; CHECK-NEXT:    %1 = getelementptr inbounds nuw %v4f32_i32.vararg, ptr %vararg_buffer, i32 0, i32 1
329; CHECK-NEXT:    store i32 %y, ptr %1, align 4
330; CHECK-NEXT:    call void @vararg(ptr %vararg_buffer)
331; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 20, ptr %vararg_buffer)
332; CHECK-NEXT:    ret void
333;
334entry:
335  tail call void (...) @vararg(<4 x float> noundef %x, i32 noundef %y)
336  ret void
337}
338
339define hidden void @i32_v8f32(i32 noundef %x, <8 x float> noundef %y) {
340; CHECK-LABEL: define {{[^@]+}}@i32_v8f32(i32 noundef %x, <8 x float> noundef %y) {
341; CHECK-NEXT:  entry:
342; CHECK-NEXT:    %vararg_buffer = alloca %i32_v8f32.vararg, align 32
343; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 64, ptr %vararg_buffer)
344; CHECK-NEXT:    %0 = getelementptr inbounds nuw %i32_v8f32.vararg, ptr %vararg_buffer, i32 0, i32 0
345; CHECK-NEXT:    store i32 %x, ptr %0, align 4
346; CHECK-NEXT:    %1 = getelementptr inbounds nuw %i32_v8f32.vararg, ptr %vararg_buffer, i32 0, i32 2
347; CHECK-NEXT:    store <8 x float> %y, ptr %1, align 32
348; CHECK-NEXT:    call void @vararg(ptr %vararg_buffer)
349; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 64, ptr %vararg_buffer)
350; CHECK-NEXT:    ret void
351;
352entry:
353  tail call void (...) @vararg(i32 noundef %x, <8 x float> noundef %y)
354  ret void
355}
356
357define hidden void @v8f32_i32(<8 x float> noundef %x, i32 noundef %y) {
358; CHECK-LABEL: define {{[^@]+}}@v8f32_i32(<8 x float> noundef %x, i32 noundef %y) {
359; CHECK-NEXT:  entry:
360; CHECK-NEXT:    %vararg_buffer = alloca %v8f32_i32.vararg, align 32
361; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 36, ptr %vararg_buffer)
362; CHECK-NEXT:    %0 = getelementptr inbounds nuw %v8f32_i32.vararg, ptr %vararg_buffer, i32 0, i32 0
363; CHECK-NEXT:    store <8 x float> %x, ptr %0, align 32
364; CHECK-NEXT:    %1 = getelementptr inbounds nuw %v8f32_i32.vararg, ptr %vararg_buffer, i32 0, i32 1
365; CHECK-NEXT:    store i32 %y, ptr %1, align 4
366; CHECK-NEXT:    call void @vararg(ptr %vararg_buffer)
367; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 36, ptr %vararg_buffer)
368; CHECK-NEXT:    ret void
369;
370entry:
371  tail call void (...) @vararg(<8 x float> noundef %x, i32 noundef %y)
372  ret void
373}
374
375define hidden void @i32_v16f32(i32 noundef %x, <16 x float> noundef %y) {
376; CHECK-LABEL: define {{[^@]+}}@i32_v16f32(i32 noundef %x, <16 x float> noundef %y) {
377; CHECK-NEXT:  entry:
378; CHECK-NEXT:    %vararg_buffer = alloca %i32_v16f32.vararg, align 64
379; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 128, ptr %vararg_buffer)
380; CHECK-NEXT:    %0 = getelementptr inbounds nuw %i32_v16f32.vararg, ptr %vararg_buffer, i32 0, i32 0
381; CHECK-NEXT:    store i32 %x, ptr %0, align 4
382; CHECK-NEXT:    %1 = getelementptr inbounds nuw %i32_v16f32.vararg, ptr %vararg_buffer, i32 0, i32 2
383; CHECK-NEXT:    store <16 x float> %y, ptr %1, align 64
384; CHECK-NEXT:    call void @vararg(ptr %vararg_buffer)
385; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 128, ptr %vararg_buffer)
386; CHECK-NEXT:    ret void
387;
388entry:
389  tail call void (...) @vararg(i32 noundef %x, <16 x float> noundef %y)
390  ret void
391}
392
393define hidden void @v16f32_i32(<16 x float> noundef %x, i32 noundef %y) {
394; CHECK-LABEL: define {{[^@]+}}@v16f32_i32(<16 x float> noundef %x, i32 noundef %y) {
395; CHECK-NEXT:  entry:
396; CHECK-NEXT:    %vararg_buffer = alloca %v16f32_i32.vararg, align 64
397; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 68, ptr %vararg_buffer)
398; CHECK-NEXT:    %0 = getelementptr inbounds nuw %v16f32_i32.vararg, ptr %vararg_buffer, i32 0, i32 0
399; CHECK-NEXT:    store <16 x float> %x, ptr %0, align 64
400; CHECK-NEXT:    %1 = getelementptr inbounds nuw %v16f32_i32.vararg, ptr %vararg_buffer, i32 0, i32 1
401; CHECK-NEXT:    store i32 %y, ptr %1, align 4
402; CHECK-NEXT:    call void @vararg(ptr %vararg_buffer)
403; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 68, ptr %vararg_buffer)
404; CHECK-NEXT:    ret void
405;
406entry:
407  tail call void (...) @vararg(<16 x float> noundef %x, i32 noundef %y)
408  ret void
409}
410
411define hidden void @i32_v32f32(i32 noundef %x, <32 x float> noundef %y) {
412; CHECK-LABEL: define {{[^@]+}}@i32_v32f32(i32 noundef %x, <32 x float> noundef %y) {
413; CHECK-NEXT:  entry:
414; CHECK-NEXT:    %vararg_buffer = alloca %i32_v32f32.vararg, align 128
415; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 256, ptr %vararg_buffer)
416; CHECK-NEXT:    %0 = getelementptr inbounds nuw %i32_v32f32.vararg, ptr %vararg_buffer, i32 0, i32 0
417; CHECK-NEXT:    store i32 %x, ptr %0, align 4
418; CHECK-NEXT:    %1 = getelementptr inbounds nuw %i32_v32f32.vararg, ptr %vararg_buffer, i32 0, i32 2
419; CHECK-NEXT:    store <32 x float> %y, ptr %1, align 128
420; CHECK-NEXT:    call void @vararg(ptr %vararg_buffer)
421; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 256, ptr %vararg_buffer)
422; CHECK-NEXT:    ret void
423;
424entry:
425  tail call void (...) @vararg(i32 noundef %x, <32 x float> noundef %y)
426  ret void
427}
428
429define hidden void @v32f32_i32(<32 x float> noundef %x, i32 noundef %y) {
430; CHECK-LABEL: define {{[^@]+}}@v32f32_i32(<32 x float> noundef %x, i32 noundef %y) {
431; CHECK-NEXT:  entry:
432; CHECK-NEXT:    %vararg_buffer = alloca %v32f32_i32.vararg, align 128
433; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 132, ptr %vararg_buffer)
434; CHECK-NEXT:    %0 = getelementptr inbounds nuw %v32f32_i32.vararg, ptr %vararg_buffer, i32 0, i32 0
435; CHECK-NEXT:    store <32 x float> %x, ptr %0, align 128
436; CHECK-NEXT:    %1 = getelementptr inbounds nuw %v32f32_i32.vararg, ptr %vararg_buffer, i32 0, i32 1
437; CHECK-NEXT:    store i32 %y, ptr %1, align 4
438; CHECK-NEXT:    call void @vararg(ptr %vararg_buffer)
439; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 132, ptr %vararg_buffer)
440; CHECK-NEXT:    ret void
441;
442entry:
443  tail call void (...) @vararg(<32 x float> noundef %x, i32 noundef %y)
444  ret void
445}
446
447define hidden void @fptr_single_i32(i32 noundef %x) {
448; CHECK-LABEL: define {{[^@]+}}@fptr_single_i32(i32 noundef %x) {
449; CHECK-NEXT:  entry:
450; CHECK-NEXT:    %vararg_buffer = alloca %fptr_single_i32.vararg, align 16
451; CHECK-NEXT:    %0 = load volatile ptr, ptr @vararg_ptr, align 4
452; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr %vararg_buffer)
453; CHECK-NEXT:    %1 = getelementptr inbounds nuw %fptr_single_i32.vararg, ptr %vararg_buffer, i32 0, i32 0
454; CHECK-NEXT:    store i32 %x, ptr %1, align 4
455; CHECK-NEXT:    call void %0(ptr %vararg_buffer)
456; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr %vararg_buffer)
457; CHECK-NEXT:    ret void
458;
459entry:
460  %0 = load volatile ptr, ptr @vararg_ptr, align 4
461  tail call void (...) %0(i32 noundef %x)
462  ret void
463}
464
465define hidden void @fptr_libcS(ptr noundef byval(%struct.libcS) align 8 %x) {
466; CHECK-LABEL: define {{[^@]+}}@fptr_libcS(ptr noundef byval(%struct.libcS) align 8 %x) {
467; CHECK-NEXT:  entry:
468; CHECK-NEXT:    %IndirectAlloca = alloca %struct.libcS, align 8
469; CHECK-NEXT:    %vararg_buffer = alloca %fptr_libcS.vararg, align 16
470; CHECK-NEXT:    %0 = load volatile ptr, ptr @vararg_ptr, align 4
471; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr %IndirectAlloca, ptr %x, i64 24, i1 false)
472; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr %vararg_buffer)
473; CHECK-NEXT:    %1 = getelementptr inbounds nuw %fptr_libcS.vararg, ptr %vararg_buffer, i32 0, i32 0
474; CHECK-NEXT:    store ptr %IndirectAlloca, ptr %1, align 4
475; CHECK-NEXT:    call void %0(ptr %vararg_buffer)
476; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 4, ptr %vararg_buffer)
477; CHECK-NEXT:    ret void
478;
479entry:
480  %0 = load volatile ptr, ptr @vararg_ptr, align 4
481  tail call void (...) %0(ptr noundef nonnull byval(%struct.libcS) align 8 %x)
482  ret void
483}
484
485