[clang] [llvm] [LLVM] Fix incorrect alignment on AMDGPU variadics (PR #96370)

Joseph Huber via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 21 18:00:52 PDT 2024


https://github.com/jhuber6 created https://github.com/llvm/llvm-project/pull/96370

Summary:
The variadics lowering for AMDGPU puts all the arguments into a void
pointer struct. The current logic dictates that the minimum alignment is
four regardless of what  the underlying type is. This is incorrect in
the following case.

```c
void foo(int, ...);

void bar() {
  int x;
  void *p;
  foo(0, x, p);
}
```
Here, because the minimum alignment is 4, we will only increment the
buffer by 4, resulting in an incorrect alignment when we then try to
access the void pointer. We need to set a minimum of 4, but increase it
to 8 in cases like this.


>From 5ee5bccb5dd4bd1d78dc04ead3c334d88b86f4fd Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Fri, 21 Jun 2024 19:17:42 -0500
Subject: [PATCH] [LLVM] Fix incorrect alignment on AMDGPU variadics

Summary:
The variadics lowering for AMDGPU puts all the arguments into a void
pointer struct. The current logic dictates that the minimum alignment is
four regardless of what  the underlying type is. This is incorrect in
the following case.

```c
void foo(int, ...);

void bar() {
  int x;
  void *p;
  foo(0, x, p);
}
```
Here, because the minimum alignment is 4, we will only increment the
buffer by 4, resulting in an incorrect alignment when we then try to
access the void pointer. We need to set a minimum of 4, but increase it
to 8 in cases like this.
---
 clang/lib/CodeGen/Targets/AMDGPU.cpp          |  11 +-
 clang/test/CodeGen/amdgpu-variadic-call.c     |  32 +-
 llvm/lib/Transforms/IPO/ExpandVariadics.cpp   |   6 +-
 .../CodeGen/AMDGPU/expand-variadic-call.ll    | 574 +++++++++---------
 4 files changed, 316 insertions(+), 307 deletions(-)

diff --git a/clang/lib/CodeGen/Targets/AMDGPU.cpp b/clang/lib/CodeGen/Targets/AMDGPU.cpp
index 4d3275e17c386..a169a7d920456 100644
--- a/clang/lib/CodeGen/Targets/AMDGPU.cpp
+++ b/clang/lib/CodeGen/Targets/AMDGPU.cpp
@@ -121,7 +121,7 @@ void AMDGPUABIInfo::computeInfo(CGFunctionInfo &FI) const {
 RValue AMDGPUABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
                                 QualType Ty, AggValueSlot Slot) const {
   const bool IsIndirect = false;
-  const bool AllowHigherAlign = false;
+  const bool AllowHigherAlign = true;
   return emitVoidPtrVAArg(CGF, VAListAddr, Ty, IsIndirect,
                           getContext().getTypeInfoInChars(Ty),
                           CharUnits::fromQuantity(4), AllowHigherAlign, Slot);
@@ -212,13 +212,8 @@ ABIArgInfo AMDGPUABIInfo::classifyArgumentType(QualType Ty, bool Variadic,
 
   Ty = useFirstFieldIfTransparentUnion(Ty);
 
-  if (Variadic) {
-    return ABIArgInfo::getDirect(/*T=*/nullptr,
-                                 /*Offset=*/0,
-                                 /*Padding=*/nullptr,
-                                 /*CanBeFlattened=*/false,
-                                 /*Align=*/0);
-  }
+  if (Variadic)
+    return ABIArgInfo::getDirect();
 
   if (isAggregateTypeForABI(Ty)) {
     // Records with non-trivial destructors/copy-constructors should not be
diff --git a/clang/test/CodeGen/amdgpu-variadic-call.c b/clang/test/CodeGen/amdgpu-variadic-call.c
index 17eda215211a2..0529d6b3171c8 100644
--- a/clang/test/CodeGen/amdgpu-variadic-call.c
+++ b/clang/test/CodeGen/amdgpu-variadic-call.c
@@ -1,4 +1,3 @@
-// REQUIRES: amdgpu-registered-target
 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature
 // RUN: %clang_cc1 -cc1 -std=c23 -triple amdgcn-amd-amdhsa -emit-llvm -O1 %s -o - | FileCheck %s
 
@@ -179,11 +178,9 @@ typedef struct
 // CHECK-LABEL: define {{[^@]+}}@one_pair_f64
 // CHECK-SAME: (i32 noundef [[F0:%.*]], double noundef [[F1:%.*]], double [[V0_COERCE0:%.*]], double [[V0_COERCE1:%.*]]) local_unnamed_addr #[[ATTR0]] {
 // CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[DOTFCA_0_INSERT:%.*]] = insertvalue [[STRUCT_PAIR_F64:%.*]] poison, double [[V0_COERCE0]], 0
-// CHECK-NEXT:    [[DOTFCA_1_INSERT:%.*]] = insertvalue [[STRUCT_PAIR_F64]] [[DOTFCA_0_INSERT]], double [[V0_COERCE1]], 1
-// CHECK-NEXT:    tail call void (...) @sink_0([[STRUCT_PAIR_F64]] [[DOTFCA_1_INSERT]]) #[[ATTR2]]
-// CHECK-NEXT:    tail call void (i32, ...) @sink_1(i32 noundef [[F0]], [[STRUCT_PAIR_F64]] [[DOTFCA_1_INSERT]]) #[[ATTR2]]
-// CHECK-NEXT:    tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], [[STRUCT_PAIR_F64]] [[DOTFCA_1_INSERT]]) #[[ATTR2]]
+// CHECK-NEXT:    tail call void (...) @sink_0(double [[V0_COERCE0]], double [[V0_COERCE1]]) #[[ATTR2]]
+// CHECK-NEXT:    tail call void (i32, ...) @sink_1(i32 noundef [[F0]], double [[V0_COERCE0]], double [[V0_COERCE1]]) #[[ATTR2]]
+// CHECK-NEXT:    tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], double [[V0_COERCE0]], double [[V0_COERCE1]]) #[[ATTR2]]
 // CHECK-NEXT:    ret void
 //
 void one_pair_f64(int f0, double f1, pair_f64 v0)
@@ -220,10 +217,9 @@ typedef union
 // CHECK-SAME: (i32 noundef [[F0:%.*]], double noundef [[F1:%.*]], i32 [[V0_COERCE:%.*]]) local_unnamed_addr #[[ATTR0]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast i32 [[V0_COERCE]] to float
-// CHECK-NEXT:    [[DOTFCA_0_INSERT:%.*]] = insertvalue [[UNION_UNION_F32_I32:%.*]] poison, float [[TMP0]], 0
-// CHECK-NEXT:    tail call void (...) @sink_0([[UNION_UNION_F32_I32]] [[DOTFCA_0_INSERT]]) #[[ATTR2]]
-// CHECK-NEXT:    tail call void (i32, ...) @sink_1(i32 noundef [[F0]], [[UNION_UNION_F32_I32]] [[DOTFCA_0_INSERT]]) #[[ATTR2]]
-// CHECK-NEXT:    tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], [[UNION_UNION_F32_I32]] [[DOTFCA_0_INSERT]]) #[[ATTR2]]
+// CHECK-NEXT:    tail call void (...) @sink_0(float [[TMP0]]) #[[ATTR2]]
+// CHECK-NEXT:    tail call void (i32, ...) @sink_1(i32 noundef [[F0]], float [[TMP0]]) #[[ATTR2]]
+// CHECK-NEXT:    tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], float [[TMP0]]) #[[ATTR2]]
 // CHECK-NEXT:    ret void
 //
 void one_pair_union_f32_i32(int f0, double f1, union_f32_i32 v0)
@@ -242,10 +238,9 @@ typedef union
 // CHECK-LABEL: define {{[^@]+}}@one_pair_transparent_union_f32_i32
 // CHECK-SAME: (i32 noundef [[F0:%.*]], double noundef [[F1:%.*]], i32 [[V0_COERCE:%.*]]) local_unnamed_addr #[[ATTR0]] {
 // CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[DOTFCA_0_INSERT:%.*]] = insertvalue [[UNION_TRANSPARENT_UNION_F32_I32:%.*]] poison, i32 [[V0_COERCE]], 0
-// CHECK-NEXT:    tail call void (...) @sink_0([[UNION_TRANSPARENT_UNION_F32_I32]] [[DOTFCA_0_INSERT]]) #[[ATTR2]]
-// CHECK-NEXT:    tail call void (i32, ...) @sink_1(i32 noundef [[F0]], [[UNION_TRANSPARENT_UNION_F32_I32]] [[DOTFCA_0_INSERT]]) #[[ATTR2]]
-// CHECK-NEXT:    tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], [[UNION_TRANSPARENT_UNION_F32_I32]] [[DOTFCA_0_INSERT]]) #[[ATTR2]]
+// CHECK-NEXT:    tail call void (...) @sink_0(i32 [[V0_COERCE]]) #[[ATTR2]]
+// CHECK-NEXT:    tail call void (i32, ...) @sink_1(i32 noundef [[F0]], i32 [[V0_COERCE]]) #[[ATTR2]]
+// CHECK-NEXT:    tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], i32 [[V0_COERCE]]) #[[ATTR2]]
 // CHECK-NEXT:    ret void
 //
 void one_pair_transparent_union_f32_i32(int f0, double f1, transparent_union_f32_i32 v0)
@@ -277,12 +272,9 @@ void multiple_one(int f0, double f1, int v0, double v1)
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast i32 [[V2_COERCE]] to float
 // CHECK-NEXT:    [[CONV:%.*]] = fpext float [[V1]] to double
-// CHECK-NEXT:    [[DOTFCA_0_INSERT16:%.*]] = insertvalue [[STRUCT_PAIR_F64:%.*]] poison, double [[V0_COERCE0]], 0
-// CHECK-NEXT:    [[DOTFCA_1_INSERT:%.*]] = insertvalue [[STRUCT_PAIR_F64]] [[DOTFCA_0_INSERT16]], double [[V0_COERCE1]], 1
-// CHECK-NEXT:    [[DOTFCA_0_INSERT:%.*]] = insertvalue [[UNION_UNION_F32_I32:%.*]] poison, float [[TMP0]], 0
-// CHECK-NEXT:    tail call void (...) @sink_0([[STRUCT_PAIR_F64]] [[DOTFCA_1_INSERT]], double noundef [[CONV]], [[UNION_UNION_F32_I32]] [[DOTFCA_0_INSERT]], i32 noundef [[V3]]) #[[ATTR2]]
-// CHECK-NEXT:    tail call void (i32, ...) @sink_1(i32 noundef [[F0]], [[STRUCT_PAIR_F64]] [[DOTFCA_1_INSERT]], double noundef [[CONV]], [[UNION_UNION_F32_I32]] [[DOTFCA_0_INSERT]], i32 noundef [[V3]]) #[[ATTR2]]
-// CHECK-NEXT:    tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], [[STRUCT_PAIR_F64]] [[DOTFCA_1_INSERT]], double noundef [[CONV]], [[UNION_UNION_F32_I32]] [[DOTFCA_0_INSERT]], i32 noundef [[V3]]) #[[ATTR2]]
+// CHECK-NEXT:    tail call void (...) @sink_0(double [[V0_COERCE0]], double [[V0_COERCE1]], double noundef [[CONV]], float [[TMP0]], i32 noundef [[V3]]) #[[ATTR2]]
+// CHECK-NEXT:    tail call void (i32, ...) @sink_1(i32 noundef [[F0]], double [[V0_COERCE0]], double [[V0_COERCE1]], double noundef [[CONV]], float [[TMP0]], i32 noundef [[V3]]) #[[ATTR2]]
+// CHECK-NEXT:    tail call void (double, i32, ...) @sink_2(double noundef [[F1]], i32 noundef [[F0]], double [[V0_COERCE0]], double [[V0_COERCE1]], double noundef [[CONV]], float [[TMP0]], i32 noundef [[V3]]) #[[ATTR2]]
 // CHECK-NEXT:    ret void
 //
 void multiple_two(int f0, double f1, pair_f64 v0, float v1, union_f32_i32 v2, int v3)
diff --git a/llvm/lib/Transforms/IPO/ExpandVariadics.cpp b/llvm/lib/Transforms/IPO/ExpandVariadics.cpp
index d340bc041ccda..489e13410d3b1 100644
--- a/llvm/lib/Transforms/IPO/ExpandVariadics.cpp
+++ b/llvm/lib/Transforms/IPO/ExpandVariadics.cpp
@@ -934,7 +934,11 @@ struct Amdgpu final : public VariadicABIInfo {
   }
 
   VAArgSlotInfo slotInfo(const DataLayout &DL, Type *Parameter) override {
-    return {Align(4), false};
+    const unsigned MinAlign = 1;
+    Align A = DL.getABITypeAlign(Parameter);
+    if (A < MinAlign)
+      A = Align(MinAlign);
+    return {A, false};
   }
 };
 
diff --git a/llvm/test/CodeGen/AMDGPU/expand-variadic-call.ll b/llvm/test/CodeGen/AMDGPU/expand-variadic-call.ll
index ce55558dabaf1..e7450707ac94a 100644
--- a/llvm/test/CodeGen/AMDGPU/expand-variadic-call.ll
+++ b/llvm/test/CodeGen/AMDGPU/expand-variadic-call.ll
@@ -1,50 +1,48 @@
-; 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
-; REQUIRES: amdgpu-registered-target
-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"
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -mtriple=amdgcn-- --passes=expand-variadics \
+; RUN:   --expand-variadics-override=lowering < %s | FileCheck %s
 
-; Check the variables are lowered to the locations this target expects
+%struct.libcS = type { i8, i16, i32, i64, float, double }
 
-; The types show the call frames
+; 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: %i32_double.vararg = type <{ i32, [4 x i8], double }>
 ; CHECK: %double_i32.vararg = type <{ double, i32 }>
-; CHECK: %i32_libcS.vararg = type <{ i32, %struct.libcS }>
+; CHECK: %i32_libcS.vararg = type <{ i32, [4 x i8], %struct.libcS }>
+; CHECK: %struct.libcS = type { i8, i16, i32, i64, float, double }
 ; CHECK: %libcS_i32.vararg = type <{ %struct.libcS, i32 }>
-; CHECK: %i32_v4f32.vararg = type <{ i32, <4 x float> }>
+; CHECK: %i32_v4f32.vararg = type <{ i32, [12 x i8], <4 x float> }>
 ; CHECK: %v4f32_i32.vararg = type <{ <4 x float>, i32 }>
-; CHECK: %i32_v8f32.vararg = type <{ i32, <8 x float> }>
+; CHECK: %i32_v8f32.vararg = type <{ i32, [28 x i8], <8 x float> }>
 ; CHECK: %v8f32_i32.vararg = type <{ <8 x float>, i32 }>
-; CHECK: %i32_v16f32.vararg = type <{ i32, <16 x float> }>
+; CHECK: %i32_v16f32.vararg = type <{ i32, [60 x i8], <16 x float> }>
 ; CHECK: %v16f32_i32.vararg = type <{ <16 x float>, i32 }>
-; CHECK: %i32_v32f32.vararg = type <{ i32, <32 x float> }>
+; CHECK: %i32_v32f32.vararg = type <{ i32, [124 x i8], <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-LABEL: define hidden void @copy(
+; CHECK-SAME: 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:    [[TMP0:%.*]] = load ptr, ptr addrspace(5) [[CP]], align 8
+; CHECK-NEXT:    call void @valist(ptr noundef [[TMP0]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[CP]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -70,15 +68,16 @@ 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-LABEL: define hidden void @start_once(
+; CHECK-SAME: 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:    [[TMP0:%.*]] = load ptr, ptr addrspace(5) [[S]], align 8
+; CHECK-NEXT:    call void @valist(ptr noundef [[TMP0]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[S]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -98,22 +97,23 @@ 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-LABEL: define hidden void @start_twice(
+; CHECK-SAME: 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:    [[TMP0:%.*]] = load ptr, ptr addrspace(5) [[S0]], align 8
+; CHECK-NEXT:    call void @valist(ptr noundef [[TMP0]])
+; CHECK-NEXT:    store ptr [[VARARGS]], ptr [[S1_ASCAST]], align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr addrspace(5) [[S1]], align 8
+; CHECK-NEXT:    call void @valist(ptr noundef [[TMP1]])
+; 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:
@@ -137,15 +137,16 @@ entry:
 }
 
 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 %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-LABEL: define hidden void @single_i32(
+; CHECK-SAME: 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:    [[TMP0:%.*]] = getelementptr inbounds [[SINGLE_I32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 0
+; CHECK-NEXT:    store i32 [[X]], ptr addrspace(5) [[TMP0]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast ptr addrspace(5) [[VARARG_BUFFER]] to ptr
+; CHECK-NEXT:    call void @vararg(ptr [[TMP1]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[VARARG_BUFFER]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -156,15 +157,16 @@ entry:
 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 %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-LABEL: define hidden void @single_double(
+; CHECK-SAME: double noundef [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[SINGLE_DOUBLE_VARARG:%.*]], align 8, addrspace(5)
+; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 8, ptr addrspace(5) [[VARARG_BUFFER]])
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[SINGLE_DOUBLE_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 0
+; CHECK-NEXT:    store double [[X]], ptr addrspace(5) [[TMP0]], align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast ptr addrspace(5) [[VARARG_BUFFER]] to ptr
+; CHECK-NEXT:    call void @vararg(ptr [[TMP1]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 8, ptr addrspace(5) [[VARARG_BUFFER]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -173,15 +175,16 @@ entry:
 }
 
 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 %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-LABEL: define hidden void @single_v4f32(
+; CHECK-SAME: <4 x float> noundef [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[SINGLE_V4F32_VARARG:%.*]], align 16, addrspace(5)
+; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 16, ptr addrspace(5) [[VARARG_BUFFER]])
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[SINGLE_V4F32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 0
+; CHECK-NEXT:    store <4 x float> [[X]], ptr addrspace(5) [[TMP0]], align 16
+; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast ptr addrspace(5) [[VARARG_BUFFER]] to ptr
+; CHECK-NEXT:    call void @vararg(ptr [[TMP1]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 16, ptr addrspace(5) [[VARARG_BUFFER]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -190,15 +193,16 @@ entry:
 }
 
 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 %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-LABEL: define hidden void @single_v8f32(
+; CHECK-SAME: <8 x float> noundef [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[SINGLE_V8F32_VARARG:%.*]], align 32, addrspace(5)
+; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 32, ptr addrspace(5) [[VARARG_BUFFER]])
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[SINGLE_V8F32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 0
+; CHECK-NEXT:    store <8 x float> [[X]], ptr addrspace(5) [[TMP0]], align 32
+; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast ptr addrspace(5) [[VARARG_BUFFER]] to ptr
+; CHECK-NEXT:    call void @vararg(ptr [[TMP1]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 32, ptr addrspace(5) [[VARARG_BUFFER]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -207,15 +211,16 @@ entry:
 }
 
 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 %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-LABEL: define hidden void @single_v16f32(
+; CHECK-SAME: <16 x float> noundef [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[SINGLE_V16F32_VARARG:%.*]], align 64, addrspace(5)
+; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 64, ptr addrspace(5) [[VARARG_BUFFER]])
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[SINGLE_V16F32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 0
+; CHECK-NEXT:    store <16 x float> [[X]], ptr addrspace(5) [[TMP0]], align 64
+; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast ptr addrspace(5) [[VARARG_BUFFER]] to ptr
+; CHECK-NEXT:    call void @vararg(ptr [[TMP1]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 64, ptr addrspace(5) [[VARARG_BUFFER]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -224,15 +229,16 @@ entry:
 }
 
 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 %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-LABEL: define hidden void @single_v32f32(
+; CHECK-SAME: <32 x float> noundef [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[SINGLE_V32F32_VARARG:%.*]], align 128, addrspace(5)
+; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 128, ptr addrspace(5) [[VARARG_BUFFER]])
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[SINGLE_V32F32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 0
+; CHECK-NEXT:    store <32 x float> [[X]], ptr addrspace(5) [[TMP0]], align 128
+; CHECK-NEXT:    [[TMP1:%.*]] = addrspacecast ptr addrspace(5) [[VARARG_BUFFER]] to ptr
+; CHECK-NEXT:    call void @vararg(ptr [[TMP1]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 128, ptr addrspace(5) [[VARARG_BUFFER]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -241,17 +247,18 @@ entry:
 }
 
 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 %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 %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-LABEL: define hidden void @i32_double(
+; CHECK-SAME: i32 noundef [[X:%.*]], double noundef [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[I32_DOUBLE_VARARG:%.*]], align 8, addrspace(5)
+; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 16, ptr addrspace(5) [[VARARG_BUFFER]])
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[I32_DOUBLE_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 0
+; CHECK-NEXT:    store i32 [[X]], ptr addrspace(5) [[TMP0]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[I32_DOUBLE_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 2
+; CHECK-NEXT:    store double [[Y]], ptr addrspace(5) [[TMP1]], align 8
+; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast ptr addrspace(5) [[VARARG_BUFFER]] to ptr
+; CHECK-NEXT:    call void @vararg(ptr [[TMP2]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 16, ptr addrspace(5) [[VARARG_BUFFER]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -260,17 +267,18 @@ entry:
 }
 
 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 %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 %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-LABEL: define hidden void @double_i32(
+; CHECK-SAME: double noundef [[X:%.*]], i32 noundef [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[DOUBLE_I32_VARARG:%.*]], align 8, addrspace(5)
+; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 12, ptr addrspace(5) [[VARARG_BUFFER]])
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[DOUBLE_I32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 0
+; CHECK-NEXT:    store double [[X]], ptr addrspace(5) [[TMP0]], align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[DOUBLE_I32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 1
+; CHECK-NEXT:    store i32 [[Y]], ptr addrspace(5) [[TMP1]], align 4
+; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast ptr addrspace(5) [[VARARG_BUFFER]] to ptr
+; CHECK-NEXT:    call void @vararg(ptr [[TMP2]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 12, ptr addrspace(5) [[VARARG_BUFFER]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -279,23 +287,24 @@ entry:
 }
 
 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 %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 %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-LABEL: define hidden void @i32_libcS(
+; CHECK-SAME: 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 8, addrspace(5)
+; CHECK-NEXT:    [[DOTFCA_0_INSERT:%.*]] = insertvalue [[STRUCT_LIBCS:%.*]] poison, i8 [[Y_COERCE0]], 0
+; CHECK-NEXT:    [[DOTFCA_1_INSERT:%.*]] = insertvalue [[STRUCT_LIBCS]] [[DOTFCA_0_INSERT]], i16 [[Y_COERCE1]], 1
+; CHECK-NEXT:    [[DOTFCA_2_INSERT:%.*]] = insertvalue [[STRUCT_LIBCS]] [[DOTFCA_1_INSERT]], i32 [[Y_COERCE2]], 2
+; CHECK-NEXT:    [[DOTFCA_3_INSERT:%.*]] = insertvalue [[STRUCT_LIBCS]] [[DOTFCA_2_INSERT]], i64 [[Y_COERCE3]], 3
+; CHECK-NEXT:    [[DOTFCA_4_INSERT:%.*]] = insertvalue [[STRUCT_LIBCS]] [[DOTFCA_3_INSERT]], float [[Y_COERCE4]], 4
+; CHECK-NEXT:    [[DOTFCA_5_INSERT:%.*]] = insertvalue [[STRUCT_LIBCS]] [[DOTFCA_4_INSERT]], double [[Y_COERCE5]], 5
+; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 40, ptr addrspace(5) [[VARARG_BUFFER]])
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[I32_LIBCS_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 0
+; CHECK-NEXT:    store i32 [[X]], ptr addrspace(5) [[TMP0]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[I32_LIBCS_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 2
+; CHECK-NEXT:    store [[STRUCT_LIBCS]] [[DOTFCA_5_INSERT]], ptr addrspace(5) [[TMP1]], align 8
+; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast ptr addrspace(5) [[VARARG_BUFFER]] to ptr
+; CHECK-NEXT:    call void @vararg(ptr [[TMP2]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 40, ptr addrspace(5) [[VARARG_BUFFER]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -310,23 +319,24 @@ entry:
 }
 
 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 %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 %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-LABEL: define hidden void @libcS_i32(
+; CHECK-SAME: 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 8, addrspace(5)
+; CHECK-NEXT:    [[DOTFCA_0_INSERT:%.*]] = insertvalue [[STRUCT_LIBCS:%.*]] poison, i8 [[X_COERCE0]], 0
+; CHECK-NEXT:    [[DOTFCA_1_INSERT:%.*]] = insertvalue [[STRUCT_LIBCS]] [[DOTFCA_0_INSERT]], i16 [[X_COERCE1]], 1
+; CHECK-NEXT:    [[DOTFCA_2_INSERT:%.*]] = insertvalue [[STRUCT_LIBCS]] [[DOTFCA_1_INSERT]], i32 [[X_COERCE2]], 2
+; CHECK-NEXT:    [[DOTFCA_3_INSERT:%.*]] = insertvalue [[STRUCT_LIBCS]] [[DOTFCA_2_INSERT]], i64 [[X_COERCE3]], 3
+; CHECK-NEXT:    [[DOTFCA_4_INSERT:%.*]] = insertvalue [[STRUCT_LIBCS]] [[DOTFCA_3_INSERT]], float [[X_COERCE4]], 4
+; CHECK-NEXT:    [[DOTFCA_5_INSERT:%.*]] = insertvalue [[STRUCT_LIBCS]] [[DOTFCA_4_INSERT]], double [[X_COERCE5]], 5
+; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 36, ptr addrspace(5) [[VARARG_BUFFER]])
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[LIBCS_I32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 0
+; CHECK-NEXT:    store [[STRUCT_LIBCS]] [[DOTFCA_5_INSERT]], ptr addrspace(5) [[TMP0]], align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[LIBCS_I32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 1
+; CHECK-NEXT:    store i32 [[Y]], ptr addrspace(5) [[TMP1]], align 4
+; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast ptr addrspace(5) [[VARARG_BUFFER]] to ptr
+; CHECK-NEXT:    call void @vararg(ptr [[TMP2]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 36, ptr addrspace(5) [[VARARG_BUFFER]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -341,17 +351,18 @@ entry:
 }
 
 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 %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 %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-LABEL: define hidden void @i32_v4f32(
+; CHECK-SAME: i32 noundef [[X:%.*]], <4 x float> noundef [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[I32_V4F32_VARARG:%.*]], align 16, addrspace(5)
+; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 32, ptr addrspace(5) [[VARARG_BUFFER]])
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[I32_V4F32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 0
+; CHECK-NEXT:    store i32 [[X]], ptr addrspace(5) [[TMP0]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[I32_V4F32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 2
+; CHECK-NEXT:    store <4 x float> [[Y]], ptr addrspace(5) [[TMP1]], align 16
+; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast ptr addrspace(5) [[VARARG_BUFFER]] to ptr
+; CHECK-NEXT:    call void @vararg(ptr [[TMP2]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 32, ptr addrspace(5) [[VARARG_BUFFER]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -360,17 +371,18 @@ entry:
 }
 
 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 %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 %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-LABEL: define hidden void @v4f32_i32(
+; CHECK-SAME: <4 x float> noundef [[X:%.*]], i32 noundef [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[V4F32_I32_VARARG:%.*]], align 16, addrspace(5)
+; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 20, ptr addrspace(5) [[VARARG_BUFFER]])
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[V4F32_I32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 0
+; CHECK-NEXT:    store <4 x float> [[X]], ptr addrspace(5) [[TMP0]], align 16
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[V4F32_I32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 1
+; CHECK-NEXT:    store i32 [[Y]], ptr addrspace(5) [[TMP1]], align 4
+; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast ptr addrspace(5) [[VARARG_BUFFER]] to ptr
+; CHECK-NEXT:    call void @vararg(ptr [[TMP2]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 20, ptr addrspace(5) [[VARARG_BUFFER]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -379,17 +391,18 @@ entry:
 }
 
 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 %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 %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-LABEL: define hidden void @i32_v8f32(
+; CHECK-SAME: i32 noundef [[X:%.*]], <8 x float> noundef [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[I32_V8F32_VARARG:%.*]], align 32, addrspace(5)
+; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 64, ptr addrspace(5) [[VARARG_BUFFER]])
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[I32_V8F32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 0
+; CHECK-NEXT:    store i32 [[X]], ptr addrspace(5) [[TMP0]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[I32_V8F32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 2
+; CHECK-NEXT:    store <8 x float> [[Y]], ptr addrspace(5) [[TMP1]], align 32
+; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast ptr addrspace(5) [[VARARG_BUFFER]] to ptr
+; CHECK-NEXT:    call void @vararg(ptr [[TMP2]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 64, ptr addrspace(5) [[VARARG_BUFFER]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -398,17 +411,18 @@ entry:
 }
 
 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 %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 %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-LABEL: define hidden void @v8f32_i32(
+; CHECK-SAME: <8 x float> noundef [[X:%.*]], i32 noundef [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[V8F32_I32_VARARG:%.*]], align 32, addrspace(5)
+; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 36, ptr addrspace(5) [[VARARG_BUFFER]])
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[V8F32_I32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 0
+; CHECK-NEXT:    store <8 x float> [[X]], ptr addrspace(5) [[TMP0]], align 32
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[V8F32_I32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 1
+; CHECK-NEXT:    store i32 [[Y]], ptr addrspace(5) [[TMP1]], align 4
+; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast ptr addrspace(5) [[VARARG_BUFFER]] to ptr
+; CHECK-NEXT:    call void @vararg(ptr [[TMP2]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 36, ptr addrspace(5) [[VARARG_BUFFER]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -417,17 +431,18 @@ entry:
 }
 
 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 %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 %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-LABEL: define hidden void @i32_v16f32(
+; CHECK-SAME: i32 noundef [[X:%.*]], <16 x float> noundef [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[I32_V16F32_VARARG:%.*]], align 64, addrspace(5)
+; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 128, ptr addrspace(5) [[VARARG_BUFFER]])
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[I32_V16F32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 0
+; CHECK-NEXT:    store i32 [[X]], ptr addrspace(5) [[TMP0]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[I32_V16F32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 2
+; CHECK-NEXT:    store <16 x float> [[Y]], ptr addrspace(5) [[TMP1]], align 64
+; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast ptr addrspace(5) [[VARARG_BUFFER]] to ptr
+; CHECK-NEXT:    call void @vararg(ptr [[TMP2]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 128, ptr addrspace(5) [[VARARG_BUFFER]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -436,17 +451,18 @@ entry:
 }
 
 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 %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 %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-LABEL: define hidden void @v16f32_i32(
+; CHECK-SAME: <16 x float> noundef [[X:%.*]], i32 noundef [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[V16F32_I32_VARARG:%.*]], align 64, addrspace(5)
+; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 68, ptr addrspace(5) [[VARARG_BUFFER]])
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[V16F32_I32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 0
+; CHECK-NEXT:    store <16 x float> [[X]], ptr addrspace(5) [[TMP0]], align 64
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[V16F32_I32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 1
+; CHECK-NEXT:    store i32 [[Y]], ptr addrspace(5) [[TMP1]], align 4
+; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast ptr addrspace(5) [[VARARG_BUFFER]] to ptr
+; CHECK-NEXT:    call void @vararg(ptr [[TMP2]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 68, ptr addrspace(5) [[VARARG_BUFFER]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -455,17 +471,18 @@ entry:
 }
 
 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 %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 %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-LABEL: define hidden void @i32_v32f32(
+; CHECK-SAME: i32 noundef [[X:%.*]], <32 x float> noundef [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[I32_V32F32_VARARG:%.*]], align 128, addrspace(5)
+; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 256, ptr addrspace(5) [[VARARG_BUFFER]])
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[I32_V32F32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 0
+; CHECK-NEXT:    store i32 [[X]], ptr addrspace(5) [[TMP0]], align 4
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[I32_V32F32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 2
+; CHECK-NEXT:    store <32 x float> [[Y]], ptr addrspace(5) [[TMP1]], align 128
+; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast ptr addrspace(5) [[VARARG_BUFFER]] to ptr
+; CHECK-NEXT:    call void @vararg(ptr [[TMP2]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 256, ptr addrspace(5) [[VARARG_BUFFER]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -474,17 +491,18 @@ entry:
 }
 
 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 %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 %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-LABEL: define hidden void @v32f32_i32(
+; CHECK-SAME: <32 x float> noundef [[X:%.*]], i32 noundef [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[V32F32_I32_VARARG:%.*]], align 128, addrspace(5)
+; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 132, ptr addrspace(5) [[VARARG_BUFFER]])
+; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[V32F32_I32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 0
+; CHECK-NEXT:    store <32 x float> [[X]], ptr addrspace(5) [[TMP0]], align 128
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[V32F32_I32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 1
+; CHECK-NEXT:    store i32 [[Y]], ptr addrspace(5) [[TMP1]], align 4
+; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast ptr addrspace(5) [[VARARG_BUFFER]] to ptr
+; CHECK-NEXT:    call void @vararg(ptr [[TMP2]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 132, ptr addrspace(5) [[VARARG_BUFFER]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -493,16 +511,17 @@ entry:
 }
 
 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 %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-LABEL: define hidden void @fptr_single_i32(
+; CHECK-SAME: i32 noundef [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[VARARG_BUFFER:%.*]] = alloca [[FPTR_SINGLE_I32_VARARG:%.*]], align 4, addrspace(5)
+; CHECK-NEXT:    [[TMP0:%.*]] = 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:    [[TMP1:%.*]] = getelementptr inbounds [[FPTR_SINGLE_I32_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 0
+; CHECK-NEXT:    store i32 [[X]], ptr addrspace(5) [[TMP1]], align 4
+; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast ptr addrspace(5) [[VARARG_BUFFER]] to ptr
+; CHECK-NEXT:    call void [[TMP0]](ptr [[TMP2]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 4, ptr addrspace(5) [[VARARG_BUFFER]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -512,22 +531,23 @@ entry:
 }
 
 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 %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-LABEL: define hidden void @fptr_libcS(
+; CHECK-SAME: 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 8, addrspace(5)
+; CHECK-NEXT:    [[TMP0:%.*]] = load volatile ptr, ptr addrspacecast (ptr addrspace(1) @vararg_ptr to ptr), align 8
+; CHECK-NEXT:    [[DOTFCA_0_INSERT:%.*]] = insertvalue [[STRUCT_LIBCS:%.*]] poison, i8 [[X_COERCE0]], 0
+; CHECK-NEXT:    [[DOTFCA_1_INSERT:%.*]] = insertvalue [[STRUCT_LIBCS]] [[DOTFCA_0_INSERT]], i16 [[X_COERCE1]], 1
+; CHECK-NEXT:    [[DOTFCA_2_INSERT:%.*]] = insertvalue [[STRUCT_LIBCS]] [[DOTFCA_1_INSERT]], i32 [[X_COERCE2]], 2
+; CHECK-NEXT:    [[DOTFCA_3_INSERT:%.*]] = insertvalue [[STRUCT_LIBCS]] [[DOTFCA_2_INSERT]], i64 [[X_COERCE3]], 3
+; CHECK-NEXT:    [[DOTFCA_4_INSERT:%.*]] = insertvalue [[STRUCT_LIBCS]] [[DOTFCA_3_INSERT]], float [[X_COERCE4]], 4
+; CHECK-NEXT:    [[DOTFCA_5_INSERT:%.*]] = insertvalue [[STRUCT_LIBCS]] [[DOTFCA_4_INSERT]], double [[X_COERCE5]], 5
+; CHECK-NEXT:    call void @llvm.lifetime.start.p5(i64 32, ptr addrspace(5) [[VARARG_BUFFER]])
+; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[FPTR_LIBCS_VARARG]], ptr addrspace(5) [[VARARG_BUFFER]], i32 0, i32 0
+; CHECK-NEXT:    store [[STRUCT_LIBCS]] [[DOTFCA_5_INSERT]], ptr addrspace(5) [[TMP1]], align 8
+; CHECK-NEXT:    [[TMP2:%.*]] = addrspacecast ptr addrspace(5) [[VARARG_BUFFER]] to ptr
+; CHECK-NEXT:    call void [[TMP0]](ptr [[TMP2]])
+; CHECK-NEXT:    call void @llvm.lifetime.end.p5(i64 32, ptr addrspace(5) [[VARARG_BUFFER]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -541,5 +561,3 @@ entry:
   tail call void (...) %0(%struct.libcS %.fca.5.insert)
   ret void
 }
-
-



More information about the llvm-commits mailing list