llvm/llvm/test/CodeGen/AMDGPU/expand-variadic-call.ll

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: -p --function-signature
; RUN: opt -S --passes=expand-variadics --expand-variadics-override=lowering < %s | FileCheck %s
target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9"
target triple = "amdgcn-amd-amdhsa"

; Check the variables are lowered to the locations this target expects

; The types show the call frames
; CHECK: %single_i32.vararg = type <{ i32 }>
; CHECK: %single_double.vararg = type <{ double }>
; CHECK: %single_v4f32.vararg = type <{ <4 x float> }>
; CHECK: %single_v8f32.vararg = type <{ <8 x float> }>
; CHECK: %single_v16f32.vararg = type <{ <16 x float> }>
; CHECK: %single_v32f32.vararg = type <{ <32 x float> }>
; CHECK: %i32_double.vararg = type <{ i32, double }>
; CHECK: %double_i32.vararg = type <{ double, i32 }>
; CHECK: %i32_libcS.vararg = type <{ i32, %struct.libcS }>
; CHECK: %libcS_i32.vararg = type <{ %struct.libcS, i32 }>
; CHECK: %i32_v4f32.vararg = type <{ i32, <4 x float> }>
; CHECK: %v4f32_i32.vararg = type <{ <4 x float>, i32 }>
; CHECK: %i32_v8f32.vararg = type <{ i32, <8 x float> }>
; CHECK: %v8f32_i32.vararg = type <{ <8 x float>, i32 }>
; CHECK: %i32_v16f32.vararg = type <{ i32, <16 x float> }>
; CHECK: %v16f32_i32.vararg = type <{ <16 x float>, i32 }>
; CHECK: %i32_v32f32.vararg = type <{ i32, <32 x float> }>
; CHECK: %v32f32_i32.vararg = type <{ <32 x float>, i32 }>
; CHECK: %fptr_single_i32.vararg = type <{ i32 }>
; CHECK: %fptr_libcS.vararg = type <{ %struct.libcS }>

%struct.libcS = type { i8, i16, i32, i64, float, double }

@vararg_ptr = hidden addrspace(1) global ptr @vararg, align 8

define hidden void @copy(ptr noundef %va) {
; CHECK-LABEL: define {{[^@]+}}@copy(ptr noundef %va) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %va.addr = alloca ptr, align 8, addrspace(5)
; CHECK-NEXT:    %cp = alloca ptr, align 8, addrspace(5)
; CHECK-NEXT:    %va.addr.ascast = addrspacecast ptr addrspace(5) %va.addr to ptr
; CHECK-NEXT:    %cp.ascast = addrspacecast ptr addrspace(5) %cp to ptr
; CHECK-NEXT:    store ptr %va, ptr addrspace(5) %va.addr, align 8
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) %cp)
; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr %cp.ascast, ptr %va.addr.ascast, i32 8, i1 false)
; CHECK-NEXT:    %0 = load ptr, ptr addrspace(5) %cp, align 8
; CHECK-NEXT:    call void @valist(ptr noundef %0)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) %cp)
; CHECK-NEXT:    ret void
;
entry:
  %va.addr = alloca ptr, align 8, addrspace(5)
  %cp = alloca ptr, align 8, addrspace(5)
  %va.addr.ascast = addrspacecast ptr addrspace(5) %va.addr to ptr
  %cp.ascast = addrspacecast ptr addrspace(5) %cp to ptr
  store ptr %va, ptr addrspace(5) %va.addr, align 8
  call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) %cp)
  call void @llvm.va_copy.p0(ptr %cp.ascast, ptr nonnull %va.addr.ascast)
  %0 = load ptr, ptr addrspace(5) %cp, align 8
  call void @valist(ptr noundef %0)
  call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) %cp)
  ret void
}

declare void @llvm.lifetime.start.p5(i64 immarg, ptr addrspace(5) nocapture)

declare void @llvm.va_copy.p0(ptr, ptr)

declare hidden void @valist(ptr noundef)

declare void @llvm.lifetime.end.p5(i64 immarg, ptr addrspace(5) nocapture)

define hidden void @start_once(...) {
; CHECK-LABEL: define {{[^@]+}}@start_once(ptr %varargs) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %s = alloca ptr, align 8, addrspace(5)
; CHECK-NEXT:    %s.ascast = addrspacecast ptr addrspace(5) %s to ptr
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) %s)
; CHECK-NEXT:    store ptr %varargs, ptr %s.ascast, align 8
; CHECK-NEXT:    %0 = load ptr, ptr addrspace(5) %s, align 8
; CHECK-NEXT:    call void @valist(ptr noundef %0)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) %s)
; CHECK-NEXT:    ret void
;
entry:
  %s = alloca ptr, align 8, addrspace(5)
  %s.ascast = addrspacecast ptr addrspace(5) %s to ptr
  call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) %s)
  call void @llvm.va_start.p0(ptr %s.ascast)
  %0 = load ptr, ptr addrspace(5) %s, align 8
  call void @valist(ptr noundef %0)
  call void @llvm.va_end.p0(ptr %s.ascast)
  call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) %s)
  ret void
}

declare void @llvm.va_start.p0(ptr)

declare void @llvm.va_end.p0(ptr)

define hidden void @start_twice(...) {
; CHECK-LABEL: define {{[^@]+}}@start_twice(ptr %varargs) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %s0 = alloca ptr, align 8, addrspace(5)
; CHECK-NEXT:    %s1 = alloca ptr, align 8, addrspace(5)
; CHECK-NEXT:    %s0.ascast = addrspacecast ptr addrspace(5) %s0 to ptr
; CHECK-NEXT:    %s1.ascast = addrspacecast ptr addrspace(5) %s1 to ptr
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) %s0)
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) %s1)
; CHECK-NEXT:    store ptr %varargs, ptr %s0.ascast, align 8
; CHECK-NEXT:    %0 = load ptr, ptr addrspace(5) %s0, align 8
; CHECK-NEXT:    call void @valist(ptr noundef %0)
; CHECK-NEXT:    store ptr %varargs, ptr %s1.ascast, align 8
; CHECK-NEXT:    %1 = load ptr, ptr addrspace(5) %s1, align 8
; CHECK-NEXT:    call void @valist(ptr noundef %1)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) %s1)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) %s0)
; CHECK-NEXT:    ret void
;
entry:
  %s0 = alloca ptr, align 8, addrspace(5)
  %s1 = alloca ptr, align 8, addrspace(5)
  %s0.ascast = addrspacecast ptr addrspace(5) %s0 to ptr
  %s1.ascast = addrspacecast ptr addrspace(5) %s1 to ptr
  call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) %s0)
  call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) %s1)
  call void @llvm.va_start.p0(ptr %s0.ascast)
  %0 = load ptr, ptr addrspace(5) %s0, align 8
  call void @valist(ptr noundef %0)
  call void @llvm.va_end.p0(ptr %s0.ascast)
  call void @llvm.va_start.p0(ptr %s1.ascast)
  %1 = load ptr, ptr addrspace(5) %s1, align 8
  call void @valist(ptr noundef %1)
  call void @llvm.va_end.p0(ptr %s1.ascast)
  call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) %s1)
  call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) %s0)
  ret void
}

define hidden void @single_i32(i32 noundef %x) {
; CHECK-LABEL: define {{[^@]+}}@single_i32(i32 noundef %x) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %vararg_buffer = alloca %single_i32.vararg, align 4, addrspace(5)
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    %0 = getelementptr inbounds nuw %single_i32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 0
; CHECK-NEXT:    store i32 %x, ptr addrspace(5) %0, align 4
; CHECK-NEXT:    %1 = addrspacecast ptr addrspace(5) %vararg_buffer to ptr
; CHECK-NEXT:    call void @vararg(ptr %1)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    ret void
;
entry:
  tail call void (...) @vararg(i32 noundef %x)
  ret void
}

declare hidden void @vararg(...)

define hidden void @single_double(double noundef %x) {
; CHECK-LABEL: define {{[^@]+}}@single_double(double noundef %x) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %vararg_buffer = alloca %single_double.vararg, align 4, addrspace(5)
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    %0 = getelementptr inbounds nuw %single_double.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 0
; CHECK-NEXT:    store double %x, ptr addrspace(5) %0, align 8
; CHECK-NEXT:    %1 = addrspacecast ptr addrspace(5) %vararg_buffer to ptr
; CHECK-NEXT:    call void @vararg(ptr %1)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    ret void
;
entry:
  tail call void (...) @vararg(double noundef %x)
  ret void
}

define hidden void @single_v4f32(<4 x float> noundef %x) {
; CHECK-LABEL: define {{[^@]+}}@single_v4f32(<4 x float> noundef %x) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %vararg_buffer = alloca %single_v4f32.vararg, align 4, addrspace(5)
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 16, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    %0 = getelementptr inbounds nuw %single_v4f32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 0
; CHECK-NEXT:    store <4 x float> %x, ptr addrspace(5) %0, align 16
; CHECK-NEXT:    %1 = addrspacecast ptr addrspace(5) %vararg_buffer to ptr
; CHECK-NEXT:    call void @vararg(ptr %1)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 16, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    ret void
;
entry:
  tail call void (...) @vararg(<4 x float> noundef %x)
  ret void
}

define hidden void @single_v8f32(<8 x float> noundef %x) {
; CHECK-LABEL: define {{[^@]+}}@single_v8f32(<8 x float> noundef %x) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %vararg_buffer = alloca %single_v8f32.vararg, align 4, addrspace(5)
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 32, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    %0 = getelementptr inbounds nuw %single_v8f32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 0
; CHECK-NEXT:    store <8 x float> %x, ptr addrspace(5) %0, align 32
; CHECK-NEXT:    %1 = addrspacecast ptr addrspace(5) %vararg_buffer to ptr
; CHECK-NEXT:    call void @vararg(ptr %1)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 32, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    ret void
;
entry:
  tail call void (...) @vararg(<8 x float> noundef %x)
  ret void
}

define hidden void @single_v16f32(<16 x float> noundef %x) {
; CHECK-LABEL: define {{[^@]+}}@single_v16f32(<16 x float> noundef %x) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %vararg_buffer = alloca %single_v16f32.vararg, align 4, addrspace(5)
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 64, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    %0 = getelementptr inbounds nuw %single_v16f32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 0
; CHECK-NEXT:    store <16 x float> %x, ptr addrspace(5) %0, align 64
; CHECK-NEXT:    %1 = addrspacecast ptr addrspace(5) %vararg_buffer to ptr
; CHECK-NEXT:    call void @vararg(ptr %1)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 64, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    ret void
;
entry:
  tail call void (...) @vararg(<16 x float> noundef %x)
  ret void
}

define hidden void @single_v32f32(<32 x float> noundef %x) {
; CHECK-LABEL: define {{[^@]+}}@single_v32f32(<32 x float> noundef %x) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %vararg_buffer = alloca %single_v32f32.vararg, align 4, addrspace(5)
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 128, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    %0 = getelementptr inbounds nuw %single_v32f32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 0
; CHECK-NEXT:    store <32 x float> %x, ptr addrspace(5) %0, align 128
; CHECK-NEXT:    %1 = addrspacecast ptr addrspace(5) %vararg_buffer to ptr
; CHECK-NEXT:    call void @vararg(ptr %1)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 128, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    ret void
;
entry:
  tail call void (...) @vararg(<32 x float> noundef %x)
  ret void
}

define hidden void @i32_double(i32 noundef %x, double noundef %y) {
; CHECK-LABEL: define {{[^@]+}}@i32_double(i32 noundef %x, double noundef %y) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %vararg_buffer = alloca %i32_double.vararg, align 4, addrspace(5)
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 12, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    %0 = getelementptr inbounds nuw %i32_double.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 0
; CHECK-NEXT:    store i32 %x, ptr addrspace(5) %0, align 4
; CHECK-NEXT:    %1 = getelementptr inbounds nuw %i32_double.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 1
; CHECK-NEXT:    store double %y, ptr addrspace(5) %1, align 8
; CHECK-NEXT:    %2 = addrspacecast ptr addrspace(5) %vararg_buffer to ptr
; CHECK-NEXT:    call void @vararg(ptr %2)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 12, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    ret void
;
entry:
  tail call void (...) @vararg(i32 noundef %x, double noundef %y)
  ret void
}

define hidden void @double_i32(double noundef %x, i32 noundef %y) {
; CHECK-LABEL: define {{[^@]+}}@double_i32(double noundef %x, i32 noundef %y) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %vararg_buffer = alloca %double_i32.vararg, align 4, addrspace(5)
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 12, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    %0 = getelementptr inbounds nuw %double_i32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 0
; CHECK-NEXT:    store double %x, ptr addrspace(5) %0, align 8
; CHECK-NEXT:    %1 = getelementptr inbounds nuw %double_i32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 1
; CHECK-NEXT:    store i32 %y, ptr addrspace(5) %1, align 4
; CHECK-NEXT:    %2 = addrspacecast ptr addrspace(5) %vararg_buffer to ptr
; CHECK-NEXT:    call void @vararg(ptr %2)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 12, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    ret void
;
entry:
  tail call void (...) @vararg(double noundef %x, i32 noundef %y)
  ret void
}

define hidden void @i32_libcS(i32 noundef %x, i8 %y.coerce0, i16 %y.coerce1, i32 %y.coerce2, i64 %y.coerce3, float %y.coerce4, double %y.coerce5) {
; CHECK-LABEL: define {{[^@]+}}@i32_libcS(i32 noundef %x, i8 %y.coerce0, i16 %y.coerce1, i32 %y.coerce2, i64 %y.coerce3, float %y.coerce4, double %y.coerce5) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %vararg_buffer = alloca %i32_libcS.vararg, align 4, addrspace(5)
; CHECK-NEXT:    %.fca.0.insert = insertvalue %struct.libcS poison, i8 %y.coerce0, 0
; CHECK-NEXT:    %.fca.1.insert = insertvalue %struct.libcS %.fca.0.insert, i16 %y.coerce1, 1
; CHECK-NEXT:    %.fca.2.insert = insertvalue %struct.libcS %.fca.1.insert, i32 %y.coerce2, 2
; CHECK-NEXT:    %.fca.3.insert = insertvalue %struct.libcS %.fca.2.insert, i64 %y.coerce3, 3
; CHECK-NEXT:    %.fca.4.insert = insertvalue %struct.libcS %.fca.3.insert, float %y.coerce4, 4
; CHECK-NEXT:    %.fca.5.insert = insertvalue %struct.libcS %.fca.4.insert, double %y.coerce5, 5
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 36, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    %0 = getelementptr inbounds nuw %i32_libcS.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 0
; CHECK-NEXT:    store i32 %x, ptr addrspace(5) %0, align 4
; CHECK-NEXT:    %1 = getelementptr inbounds nuw %i32_libcS.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 1
; CHECK-NEXT:    store %struct.libcS %.fca.5.insert, ptr addrspace(5) %1, align 8
; CHECK-NEXT:    %2 = addrspacecast ptr addrspace(5) %vararg_buffer to ptr
; CHECK-NEXT:    call void @vararg(ptr %2)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 36, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    ret void
;
entry:
  %.fca.0.insert = insertvalue %struct.libcS poison, i8 %y.coerce0, 0
  %.fca.1.insert = insertvalue %struct.libcS %.fca.0.insert, i16 %y.coerce1, 1
  %.fca.2.insert = insertvalue %struct.libcS %.fca.1.insert, i32 %y.coerce2, 2
  %.fca.3.insert = insertvalue %struct.libcS %.fca.2.insert, i64 %y.coerce3, 3
  %.fca.4.insert = insertvalue %struct.libcS %.fca.3.insert, float %y.coerce4, 4
  %.fca.5.insert = insertvalue %struct.libcS %.fca.4.insert, double %y.coerce5, 5
  tail call void (...) @vararg(i32 noundef %x, %struct.libcS %.fca.5.insert)
  ret void
}

define hidden void @libcS_i32(i8 %x.coerce0, i16 %x.coerce1, i32 %x.coerce2, i64 %x.coerce3, float %x.coerce4, double %x.coerce5, i32 noundef %y) {
; CHECK-LABEL: define {{[^@]+}}@libcS_i32(i8 %x.coerce0, i16 %x.coerce1, i32 %x.coerce2, i64 %x.coerce3, float %x.coerce4, double %x.coerce5, i32 noundef %y) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %vararg_buffer = alloca %libcS_i32.vararg, align 4, addrspace(5)
; CHECK-NEXT:    %.fca.0.insert = insertvalue %struct.libcS poison, i8 %x.coerce0, 0
; CHECK-NEXT:    %.fca.1.insert = insertvalue %struct.libcS %.fca.0.insert, i16 %x.coerce1, 1
; CHECK-NEXT:    %.fca.2.insert = insertvalue %struct.libcS %.fca.1.insert, i32 %x.coerce2, 2
; CHECK-NEXT:    %.fca.3.insert = insertvalue %struct.libcS %.fca.2.insert, i64 %x.coerce3, 3
; CHECK-NEXT:    %.fca.4.insert = insertvalue %struct.libcS %.fca.3.insert, float %x.coerce4, 4
; CHECK-NEXT:    %.fca.5.insert = insertvalue %struct.libcS %.fca.4.insert, double %x.coerce5, 5
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 36, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    %0 = getelementptr inbounds nuw %libcS_i32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 0
; CHECK-NEXT:    store %struct.libcS %.fca.5.insert, ptr addrspace(5) %0, align 8
; CHECK-NEXT:    %1 = getelementptr inbounds nuw %libcS_i32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 1
; CHECK-NEXT:    store i32 %y, ptr addrspace(5) %1, align 4
; CHECK-NEXT:    %2 = addrspacecast ptr addrspace(5) %vararg_buffer to ptr
; CHECK-NEXT:    call void @vararg(ptr %2)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 36, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    ret void
;
entry:
  %.fca.0.insert = insertvalue %struct.libcS poison, i8 %x.coerce0, 0
  %.fca.1.insert = insertvalue %struct.libcS %.fca.0.insert, i16 %x.coerce1, 1
  %.fca.2.insert = insertvalue %struct.libcS %.fca.1.insert, i32 %x.coerce2, 2
  %.fca.3.insert = insertvalue %struct.libcS %.fca.2.insert, i64 %x.coerce3, 3
  %.fca.4.insert = insertvalue %struct.libcS %.fca.3.insert, float %x.coerce4, 4
  %.fca.5.insert = insertvalue %struct.libcS %.fca.4.insert, double %x.coerce5, 5
  tail call void (...) @vararg(%struct.libcS %.fca.5.insert, i32 noundef %y)
  ret void
}

define hidden void @i32_v4f32(i32 noundef %x, <4 x float> noundef %y) {
; CHECK-LABEL: define {{[^@]+}}@i32_v4f32(i32 noundef %x, <4 x float> noundef %y) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %vararg_buffer = alloca %i32_v4f32.vararg, align 4, addrspace(5)
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 20, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    %0 = getelementptr inbounds nuw %i32_v4f32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 0
; CHECK-NEXT:    store i32 %x, ptr addrspace(5) %0, align 4
; CHECK-NEXT:    %1 = getelementptr inbounds nuw %i32_v4f32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 1
; CHECK-NEXT:    store <4 x float> %y, ptr addrspace(5) %1, align 16
; CHECK-NEXT:    %2 = addrspacecast ptr addrspace(5) %vararg_buffer to ptr
; CHECK-NEXT:    call void @vararg(ptr %2)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 20, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    ret void
;
entry:
  tail call void (...) @vararg(i32 noundef %x, <4 x float> noundef %y)
  ret void
}

define hidden void @v4f32_i32(<4 x float> noundef %x, i32 noundef %y) {
; CHECK-LABEL: define {{[^@]+}}@v4f32_i32(<4 x float> noundef %x, i32 noundef %y) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %vararg_buffer = alloca %v4f32_i32.vararg, align 4, addrspace(5)
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 20, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    %0 = getelementptr inbounds nuw %v4f32_i32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 0
; CHECK-NEXT:    store <4 x float> %x, ptr addrspace(5) %0, align 16
; CHECK-NEXT:    %1 = getelementptr inbounds nuw %v4f32_i32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 1
; CHECK-NEXT:    store i32 %y, ptr addrspace(5) %1, align 4
; CHECK-NEXT:    %2 = addrspacecast ptr addrspace(5) %vararg_buffer to ptr
; CHECK-NEXT:    call void @vararg(ptr %2)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 20, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    ret void
;
entry:
  tail call void (...) @vararg(<4 x float> noundef %x, i32 noundef %y)
  ret void
}

define hidden void @i32_v8f32(i32 noundef %x, <8 x float> noundef %y) {
; CHECK-LABEL: define {{[^@]+}}@i32_v8f32(i32 noundef %x, <8 x float> noundef %y) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %vararg_buffer = alloca %i32_v8f32.vararg, align 4, addrspace(5)
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 36, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    %0 = getelementptr inbounds nuw %i32_v8f32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 0
; CHECK-NEXT:    store i32 %x, ptr addrspace(5) %0, align 4
; CHECK-NEXT:    %1 = getelementptr inbounds nuw %i32_v8f32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 1
; CHECK-NEXT:    store <8 x float> %y, ptr addrspace(5) %1, align 32
; CHECK-NEXT:    %2 = addrspacecast ptr addrspace(5) %vararg_buffer to ptr
; CHECK-NEXT:    call void @vararg(ptr %2)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 36, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    ret void
;
entry:
  tail call void (...) @vararg(i32 noundef %x, <8 x float> noundef %y)
  ret void
}

define hidden void @v8f32_i32(<8 x float> noundef %x, i32 noundef %y) {
; CHECK-LABEL: define {{[^@]+}}@v8f32_i32(<8 x float> noundef %x, i32 noundef %y) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %vararg_buffer = alloca %v8f32_i32.vararg, align 4, addrspace(5)
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 36, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    %0 = getelementptr inbounds nuw %v8f32_i32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 0
; CHECK-NEXT:    store <8 x float> %x, ptr addrspace(5) %0, align 32
; CHECK-NEXT:    %1 = getelementptr inbounds nuw %v8f32_i32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 1
; CHECK-NEXT:    store i32 %y, ptr addrspace(5) %1, align 4
; CHECK-NEXT:    %2 = addrspacecast ptr addrspace(5) %vararg_buffer to ptr
; CHECK-NEXT:    call void @vararg(ptr %2)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 36, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    ret void
;
entry:
  tail call void (...) @vararg(<8 x float> noundef %x, i32 noundef %y)
  ret void
}

define hidden void @i32_v16f32(i32 noundef %x, <16 x float> noundef %y) {
; CHECK-LABEL: define {{[^@]+}}@i32_v16f32(i32 noundef %x, <16 x float> noundef %y) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %vararg_buffer = alloca %i32_v16f32.vararg, align 4, addrspace(5)
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 68, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    %0 = getelementptr inbounds nuw %i32_v16f32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 0
; CHECK-NEXT:    store i32 %x, ptr addrspace(5) %0, align 4
; CHECK-NEXT:    %1 = getelementptr inbounds nuw %i32_v16f32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 1
; CHECK-NEXT:    store <16 x float> %y, ptr addrspace(5) %1, align 64
; CHECK-NEXT:    %2 = addrspacecast ptr addrspace(5) %vararg_buffer to ptr
; CHECK-NEXT:    call void @vararg(ptr %2)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 68, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    ret void
;
entry:
  tail call void (...) @vararg(i32 noundef %x, <16 x float> noundef %y)
  ret void
}

define hidden void @v16f32_i32(<16 x float> noundef %x, i32 noundef %y) {
; CHECK-LABEL: define {{[^@]+}}@v16f32_i32(<16 x float> noundef %x, i32 noundef %y) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %vararg_buffer = alloca %v16f32_i32.vararg, align 4, addrspace(5)
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 68, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    %0 = getelementptr inbounds nuw %v16f32_i32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 0
; CHECK-NEXT:    store <16 x float> %x, ptr addrspace(5) %0, align 64
; CHECK-NEXT:    %1 = getelementptr inbounds nuw %v16f32_i32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 1
; CHECK-NEXT:    store i32 %y, ptr addrspace(5) %1, align 4
; CHECK-NEXT:    %2 = addrspacecast ptr addrspace(5) %vararg_buffer to ptr
; CHECK-NEXT:    call void @vararg(ptr %2)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 68, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    ret void
;
entry:
  tail call void (...) @vararg(<16 x float> noundef %x, i32 noundef %y)
  ret void
}

define hidden void @i32_v32f32(i32 noundef %x, <32 x float> noundef %y) {
; CHECK-LABEL: define {{[^@]+}}@i32_v32f32(i32 noundef %x, <32 x float> noundef %y) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %vararg_buffer = alloca %i32_v32f32.vararg, align 4, addrspace(5)
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 132, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    %0 = getelementptr inbounds nuw %i32_v32f32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 0
; CHECK-NEXT:    store i32 %x, ptr addrspace(5) %0, align 4
; CHECK-NEXT:    %1 = getelementptr inbounds nuw %i32_v32f32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 1
; CHECK-NEXT:    store <32 x float> %y, ptr addrspace(5) %1, align 128
; CHECK-NEXT:    %2 = addrspacecast ptr addrspace(5) %vararg_buffer to ptr
; CHECK-NEXT:    call void @vararg(ptr %2)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 132, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    ret void
;
entry:
  tail call void (...) @vararg(i32 noundef %x, <32 x float> noundef %y)
  ret void
}

define hidden void @v32f32_i32(<32 x float> noundef %x, i32 noundef %y) {
; CHECK-LABEL: define {{[^@]+}}@v32f32_i32(<32 x float> noundef %x, i32 noundef %y) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %vararg_buffer = alloca %v32f32_i32.vararg, align 4, addrspace(5)
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 132, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    %0 = getelementptr inbounds nuw %v32f32_i32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 0
; CHECK-NEXT:    store <32 x float> %x, ptr addrspace(5) %0, align 128
; CHECK-NEXT:    %1 = getelementptr inbounds nuw %v32f32_i32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 1
; CHECK-NEXT:    store i32 %y, ptr addrspace(5) %1, align 4
; CHECK-NEXT:    %2 = addrspacecast ptr addrspace(5) %vararg_buffer to ptr
; CHECK-NEXT:    call void @vararg(ptr %2)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 132, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    ret void
;
entry:
  tail call void (...) @vararg(<32 x float> noundef %x, i32 noundef %y)
  ret void
}

define hidden void @fptr_single_i32(i32 noundef %x) {
; CHECK-LABEL: define {{[^@]+}}@fptr_single_i32(i32 noundef %x) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %vararg_buffer = alloca %fptr_single_i32.vararg, align 4, addrspace(5)
; CHECK-NEXT:    %0 = load volatile ptr, ptr addrspacecast (ptr addrspace(1) @vararg_ptr to ptr), align 8
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    %1 = getelementptr inbounds nuw %fptr_single_i32.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 0
; CHECK-NEXT:    store i32 %x, ptr addrspace(5) %1, align 4
; CHECK-NEXT:    %2 = addrspacecast ptr addrspace(5) %vararg_buffer to ptr
; CHECK-NEXT:    call void %0(ptr %2)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    ret void
;
entry:
  %0 = load volatile ptr, ptr addrspacecast (ptr addrspace(1) @vararg_ptr to ptr), align 8
  tail call void (...) %0(i32 noundef %x)
  ret void
}

define hidden void @fptr_libcS(i8 %x.coerce0, i16 %x.coerce1, i32 %x.coerce2, i64 %x.coerce3, float %x.coerce4, double %x.coerce5) {
; CHECK-LABEL: define {{[^@]+}}@fptr_libcS(i8 %x.coerce0, i16 %x.coerce1, i32 %x.coerce2, i64 %x.coerce3, float %x.coerce4, double %x.coerce5) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    %vararg_buffer = alloca %fptr_libcS.vararg, align 4, addrspace(5)
; CHECK-NEXT:    %0 = load volatile ptr, ptr addrspacecast (ptr addrspace(1) @vararg_ptr to ptr), align 8
; CHECK-NEXT:    %.fca.0.insert = insertvalue %struct.libcS poison, i8 %x.coerce0, 0
; CHECK-NEXT:    %.fca.1.insert = insertvalue %struct.libcS %.fca.0.insert, i16 %x.coerce1, 1
; CHECK-NEXT:    %.fca.2.insert = insertvalue %struct.libcS %.fca.1.insert, i32 %x.coerce2, 2
; CHECK-NEXT:    %.fca.3.insert = insertvalue %struct.libcS %.fca.2.insert, i64 %x.coerce3, 3
; CHECK-NEXT:    %.fca.4.insert = insertvalue %struct.libcS %.fca.3.insert, float %x.coerce4, 4
; CHECK-NEXT:    %.fca.5.insert = insertvalue %struct.libcS %.fca.4.insert, double %x.coerce5, 5
; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 32, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    %1 = getelementptr inbounds nuw %fptr_libcS.vararg, ptr addrspace(5) %vararg_buffer, i32 0, i32 0
; CHECK-NEXT:    store %struct.libcS %.fca.5.insert, ptr addrspace(5) %1, align 8
; CHECK-NEXT:    %2 = addrspacecast ptr addrspace(5) %vararg_buffer to ptr
; CHECK-NEXT:    call void %0(ptr %2)
; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 32, ptr addrspace(5) %vararg_buffer)
; CHECK-NEXT:    ret void
;
entry:
  %0 = load volatile ptr, ptr addrspacecast (ptr addrspace(1) @vararg_ptr to ptr), align 8
  %.fca.0.insert = insertvalue %struct.libcS poison, i8 %x.coerce0, 0
  %.fca.1.insert = insertvalue %struct.libcS %.fca.0.insert, i16 %x.coerce1, 1
  %.fca.2.insert = insertvalue %struct.libcS %.fca.1.insert, i32 %x.coerce2, 2
  %.fca.3.insert = insertvalue %struct.libcS %.fca.2.insert, i64 %x.coerce3, 3
  %.fca.4.insert = insertvalue %struct.libcS %.fca.3.insert, float %x.coerce4, 4
  %.fca.5.insert = insertvalue %struct.libcS %.fca.4.insert, double %x.coerce5, 5
  tail call void (...) %0(%struct.libcS %.fca.5.insert)
  ret void
}