[clang] [llvm] [transforms] Inline simple variadic functions (PR #81058)

Jon Chesterfield via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 8 05:06:17 PST 2024


================
@@ -0,0 +1,589 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: -p --function-signature
+; RUN: opt -S --passes=expand-variadics < %s | FileCheck %s
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; 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, [4 x i8], double }>
+; CHECK: %double_i32.vararg = type <{ double, i32 }>
+; 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, [28 x i8], <8 x float> }>
+; CHECK: %v8f32_i32.vararg = type <{ <8 x float>, i32 }>
+; 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, [124 x i8], <32 x float> }>
+; CHECK: %v32f32_i32.vararg = type <{ <32 x float>, i32 }>
+
+%struct.__va_list_tag = type { i32, i32, ptr, ptr }
+%struct.libcS = type { i8, i16, i32, i64, float, double }
+
+define dso_local void @codegen_for_copy(ptr noundef %x) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@codegen_for_copy(ptr noundef %x) local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %cp = alloca [1 x %struct.__va_list_tag], align 16
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %cp) #6
+; CHECK-NEXT:    call void @llvm.va_copy(ptr nonnull %cp, ptr %x)
+; CHECK-NEXT:    call void @wrapped(ptr noundef nonnull %cp) #7
+; CHECK-NEXT:    call void @llvm.va_end(ptr %cp)
+; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %cp) #6
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cp = alloca [1 x %struct.__va_list_tag], align 16
+  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %cp) #5
+  call void @llvm.va_copy(ptr nonnull %cp, ptr %x)
+  call void @wrapped(ptr noundef nonnull %cp) #6
+  call void @llvm.va_end(ptr %cp)
+  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %cp) #5
+  ret void
+}
+
+declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1
+
+declare void @llvm.va_copy(ptr, ptr) #2
+
+declare void @wrapped(ptr noundef) local_unnamed_addr #3
+
+declare void @llvm.va_end(ptr) #2
+
+declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1
+
+define dso_local void @vararg(...) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@vararg(...) local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %va = alloca [1 x %struct.__va_list_tag], align 16
+; CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %va) #6
+; CHECK-NEXT:    call void @llvm.va_start(ptr nonnull %va)
+; CHECK-NEXT:    call void @wrapped(ptr noundef nonnull %va) #7
+; CHECK-NEXT:    call void @llvm.va_end(ptr %va)
+; CHECK-NEXT:    call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %va) #6
+; CHECK-NEXT:    ret void
+;
+entry:
+  %va = alloca [1 x %struct.__va_list_tag], align 16
+  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %va) #5
+  call void @llvm.va_start(ptr nonnull %va)
+  call void @wrapped(ptr noundef nonnull %va) #6
+  call void @llvm.va_end(ptr %va)
+  call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %va) #5
+  ret void
+}
+
+declare void @llvm.va_start(ptr) #2
+
+define dso_local void @single_i32(i32 noundef %x) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@single_i32(i32 noundef %x) local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %vararg_buffer = alloca %single_i32.vararg, align 8
+; CHECK-NEXT:    %0 = getelementptr inbounds %single_i32.vararg, ptr %vararg_buffer, i32 0, i32 0
+; CHECK-NEXT:    store i32 %x, ptr %0, align 4
+; CHECK-NEXT:    %va_list = alloca [1 x { i32, i32, ptr, ptr }], align 8
+; CHECK-NEXT:    %gp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 0
+; CHECK-NEXT:    store i32 48, ptr %gp_offset, align 4
+; CHECK-NEXT:    %fp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 1
+; CHECK-NEXT:    store i32 176, ptr %fp_offset, align 4
+; CHECK-NEXT:    %overfow_arg_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 2
+; CHECK-NEXT:    store ptr %vararg_buffer, ptr %overfow_arg_area, align 8
+; CHECK-NEXT:    %reg_save_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 3
+; CHECK-NEXT:    store ptr null, ptr %reg_save_area, align 8
+; CHECK-NEXT:    call void @wrapped(ptr %va_list) #8
+; CHECK-NEXT:    ret void
+;
+entry:
+  tail call void (...) @vararg(i32 noundef %x) #7
+  ret void
+}
+
+define dso_local void @single_double(double noundef %x) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@single_double(double noundef %x) local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %vararg_buffer = alloca %single_double.vararg, align 8
+; CHECK-NEXT:    %0 = getelementptr inbounds %single_double.vararg, ptr %vararg_buffer, i32 0, i32 0
+; CHECK-NEXT:    store double %x, ptr %0, align 8
+; CHECK-NEXT:    %va_list = alloca [1 x { i32, i32, ptr, ptr }], align 8
+; CHECK-NEXT:    %gp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 0
+; CHECK-NEXT:    store i32 48, ptr %gp_offset, align 4
+; CHECK-NEXT:    %fp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 1
+; CHECK-NEXT:    store i32 176, ptr %fp_offset, align 4
+; CHECK-NEXT:    %overfow_arg_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 2
+; CHECK-NEXT:    store ptr %vararg_buffer, ptr %overfow_arg_area, align 8
+; CHECK-NEXT:    %reg_save_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 3
+; CHECK-NEXT:    store ptr null, ptr %reg_save_area, align 8
+; CHECK-NEXT:    call void @wrapped(ptr %va_list) #8
+; CHECK-NEXT:    ret void
+;
+entry:
+  tail call void (...) @vararg(double noundef %x) #7
+  ret void
+}
+
+define dso_local void @single_v4f32(<4 x float> noundef %x) local_unnamed_addr #4 {
+; CHECK-LABEL: define {{[^@]+}}@single_v4f32(<4 x float> noundef %x) local_unnamed_addr #4 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %vararg_buffer = alloca %single_v4f32.vararg, align 16
+; CHECK-NEXT:    %0 = getelementptr inbounds %single_v4f32.vararg, ptr %vararg_buffer, i32 0, i32 0
+; CHECK-NEXT:    store <4 x float> %x, ptr %0, align 16
+; CHECK-NEXT:    %va_list = alloca [1 x { i32, i32, ptr, ptr }], align 8
+; CHECK-NEXT:    %gp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 0
+; CHECK-NEXT:    store i32 48, ptr %gp_offset, align 4
+; CHECK-NEXT:    %fp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 1
+; CHECK-NEXT:    store i32 176, ptr %fp_offset, align 4
+; CHECK-NEXT:    %overfow_arg_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 2
+; CHECK-NEXT:    store ptr %vararg_buffer, ptr %overfow_arg_area, align 8
+; CHECK-NEXT:    %reg_save_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 3
+; CHECK-NEXT:    store ptr null, ptr %reg_save_area, align 8
+; CHECK-NEXT:    call void @wrapped(ptr %va_list) #8
+; CHECK-NEXT:    ret void
+;
+entry:
+  tail call void (...) @vararg(<4 x float> noundef %x) #7
+  ret void
+}
+
+define dso_local void @single_v8f32(ptr nocapture noundef readonly byval(<8 x float>) align 32 %0) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@single_v8f32(ptr nocapture noundef readonly byval(<8 x float>) align 32 %0) local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %vararg_buffer = alloca %single_v8f32.vararg, align 32
+; CHECK-NEXT:    %indirect-arg-temp = alloca <8 x float>, align 32
+; CHECK-NEXT:    %x = load <8 x float>, ptr %0, align 32, !tbaa !3
+; CHECK-NEXT:    store <8 x float> %x, ptr %indirect-arg-temp, align 32, !tbaa !3
+; CHECK-NEXT:    %1 = getelementptr inbounds %single_v8f32.vararg, ptr %vararg_buffer, i32 0, i32 0
+; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr %1, ptr %indirect-arg-temp, i64 32, i1 false)
+; CHECK-NEXT:    %va_list = alloca [1 x { i32, i32, ptr, ptr }], align 8
+; CHECK-NEXT:    %gp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 0
+; CHECK-NEXT:    store i32 48, ptr %gp_offset, align 4
+; CHECK-NEXT:    %fp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 1
+; CHECK-NEXT:    store i32 176, ptr %fp_offset, align 4
+; CHECK-NEXT:    %overfow_arg_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 2
+; CHECK-NEXT:    store ptr %vararg_buffer, ptr %overfow_arg_area, align 8
+; CHECK-NEXT:    %reg_save_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 3
+; CHECK-NEXT:    store ptr null, ptr %reg_save_area, align 8
+; CHECK-NEXT:    call void @wrapped(ptr %va_list) #8
+; CHECK-NEXT:    ret void
+;
+entry:
+  %indirect-arg-temp = alloca <8 x float>, align 32
+  %x = load <8 x float>, ptr %0, align 32, !tbaa !4
+  store <8 x float> %x, ptr %indirect-arg-temp, align 32, !tbaa !4
+  tail call void (...) @vararg(ptr noundef nonnull byval(<8 x float>) align 32 %indirect-arg-temp) #7
+  ret void
+}
+
+define dso_local void @single_v16f32(ptr nocapture noundef readonly byval(<16 x float>) align 64 %0) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@single_v16f32(ptr nocapture noundef readonly byval(<16 x float>) align 64 %0) local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %vararg_buffer = alloca %single_v16f32.vararg, align 64
+; CHECK-NEXT:    %indirect-arg-temp = alloca <16 x float>, align 64
+; CHECK-NEXT:    %x = load <16 x float>, ptr %0, align 64, !tbaa !3
+; CHECK-NEXT:    store <16 x float> %x, ptr %indirect-arg-temp, align 64, !tbaa !3
+; CHECK-NEXT:    %1 = getelementptr inbounds %single_v16f32.vararg, ptr %vararg_buffer, i32 0, i32 0
+; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr %1, ptr %indirect-arg-temp, i64 64, i1 false)
+; CHECK-NEXT:    %va_list = alloca [1 x { i32, i32, ptr, ptr }], align 8
+; CHECK-NEXT:    %gp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 0
+; CHECK-NEXT:    store i32 48, ptr %gp_offset, align 4
+; CHECK-NEXT:    %fp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 1
+; CHECK-NEXT:    store i32 176, ptr %fp_offset, align 4
+; CHECK-NEXT:    %overfow_arg_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 2
+; CHECK-NEXT:    store ptr %vararg_buffer, ptr %overfow_arg_area, align 8
+; CHECK-NEXT:    %reg_save_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 3
+; CHECK-NEXT:    store ptr null, ptr %reg_save_area, align 8
+; CHECK-NEXT:    call void @wrapped(ptr %va_list) #8
+; CHECK-NEXT:    ret void
+;
+entry:
+  %indirect-arg-temp = alloca <16 x float>, align 64
+  %x = load <16 x float>, ptr %0, align 64, !tbaa !4
+  store <16 x float> %x, ptr %indirect-arg-temp, align 64, !tbaa !4
+  tail call void (...) @vararg(ptr noundef nonnull byval(<16 x float>) align 64 %indirect-arg-temp) #7
+  ret void
+}
+
+define dso_local void @single_v32f32(ptr nocapture noundef readonly byval(<32 x float>) align 128 %0) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@single_v32f32(ptr nocapture noundef readonly byval(<32 x float>) align 128 %0) local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %vararg_buffer = alloca %single_v32f32.vararg, align 128
+; CHECK-NEXT:    %indirect-arg-temp = alloca <32 x float>, align 128
+; CHECK-NEXT:    %x = load <32 x float>, ptr %0, align 128, !tbaa !3
+; CHECK-NEXT:    store <32 x float> %x, ptr %indirect-arg-temp, align 128, !tbaa !3
+; CHECK-NEXT:    %1 = getelementptr inbounds %single_v32f32.vararg, ptr %vararg_buffer, i32 0, i32 0
+; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr %1, ptr %indirect-arg-temp, i64 128, i1 false)
+; CHECK-NEXT:    %va_list = alloca [1 x { i32, i32, ptr, ptr }], align 8
+; CHECK-NEXT:    %gp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 0
+; CHECK-NEXT:    store i32 48, ptr %gp_offset, align 4
+; CHECK-NEXT:    %fp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 1
+; CHECK-NEXT:    store i32 176, ptr %fp_offset, align 4
+; CHECK-NEXT:    %overfow_arg_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 2
+; CHECK-NEXT:    store ptr %vararg_buffer, ptr %overfow_arg_area, align 8
+; CHECK-NEXT:    %reg_save_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 3
+; CHECK-NEXT:    store ptr null, ptr %reg_save_area, align 8
+; CHECK-NEXT:    call void @wrapped(ptr %va_list) #8
+; CHECK-NEXT:    ret void
+;
+entry:
+  %indirect-arg-temp = alloca <32 x float>, align 128
+  %x = load <32 x float>, ptr %0, align 128, !tbaa !4
+  store <32 x float> %x, ptr %indirect-arg-temp, align 128, !tbaa !4
+  tail call void (...) @vararg(ptr noundef nonnull byval(<32 x float>) align 128 %indirect-arg-temp) #7
+  ret void
+}
+
+define dso_local void @i32_double(i32 noundef %x, double noundef %y) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@i32_double(i32 noundef %x, double noundef %y) local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %vararg_buffer = alloca %i32_double.vararg, align 8
+; CHECK-NEXT:    %0 = getelementptr inbounds %i32_double.vararg, ptr %vararg_buffer, i32 0, i32 0
+; CHECK-NEXT:    store i32 %x, ptr %0, align 4
+; CHECK-NEXT:    %1 = getelementptr inbounds %i32_double.vararg, ptr %vararg_buffer, i32 0, i32 2
+; CHECK-NEXT:    store double %y, ptr %1, align 8
+; CHECK-NEXT:    %va_list = alloca [1 x { i32, i32, ptr, ptr }], align 8
+; CHECK-NEXT:    %gp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 0
+; CHECK-NEXT:    store i32 48, ptr %gp_offset, align 4
+; CHECK-NEXT:    %fp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 1
+; CHECK-NEXT:    store i32 176, ptr %fp_offset, align 4
+; CHECK-NEXT:    %overfow_arg_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 2
+; CHECK-NEXT:    store ptr %vararg_buffer, ptr %overfow_arg_area, align 8
+; CHECK-NEXT:    %reg_save_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 3
+; CHECK-NEXT:    store ptr null, ptr %reg_save_area, align 8
+; CHECK-NEXT:    call void @wrapped(ptr %va_list) #8
+; CHECK-NEXT:    ret void
+;
+entry:
+  tail call void (...) @vararg(i32 noundef %x, double noundef %y) #7
+  ret void
+}
+
+define dso_local void @double_i32(double noundef %x, i32 noundef %y) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@double_i32(double noundef %x, i32 noundef %y) local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %vararg_buffer = alloca %double_i32.vararg, align 8
+; CHECK-NEXT:    %0 = getelementptr inbounds %double_i32.vararg, ptr %vararg_buffer, i32 0, i32 0
+; CHECK-NEXT:    store double %x, ptr %0, align 8
+; CHECK-NEXT:    %1 = getelementptr inbounds %double_i32.vararg, ptr %vararg_buffer, i32 0, i32 1
+; CHECK-NEXT:    store i32 %y, ptr %1, align 4
+; CHECK-NEXT:    %va_list = alloca [1 x { i32, i32, ptr, ptr }], align 8
+; CHECK-NEXT:    %gp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 0
+; CHECK-NEXT:    store i32 48, ptr %gp_offset, align 4
+; CHECK-NEXT:    %fp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 1
+; CHECK-NEXT:    store i32 176, ptr %fp_offset, align 4
+; CHECK-NEXT:    %overfow_arg_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 2
+; CHECK-NEXT:    store ptr %vararg_buffer, ptr %overfow_arg_area, align 8
+; CHECK-NEXT:    %reg_save_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 3
+; CHECK-NEXT:    store ptr null, ptr %reg_save_area, align 8
+; CHECK-NEXT:    call void @wrapped(ptr %va_list) #8
+; CHECK-NEXT:    ret void
+;
+entry:
+  tail call void (...) @vararg(double noundef %x, i32 noundef %y) #7
+  ret void
+}
+
+define dso_local void @i32_libcS(i32 noundef %x, ptr noundef byval(%struct.libcS) align 8 %y) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@i32_libcS(i32 noundef %x, ptr noundef byval(%struct.libcS) align 8 %y) local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %vararg_buffer = alloca %i32_libcS.vararg, align 8
+; CHECK-NEXT:    %0 = getelementptr inbounds %i32_libcS.vararg, ptr %vararg_buffer, i32 0, i32 0
+; CHECK-NEXT:    store i32 %x, ptr %0, align 4
+; CHECK-NEXT:    %1 = getelementptr inbounds %i32_libcS.vararg, ptr %vararg_buffer, i32 0, i32 2
+; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr %1, ptr %y, i64 32, i1 false)
+; CHECK-NEXT:    %va_list = alloca [1 x { i32, i32, ptr, ptr }], align 8
+; CHECK-NEXT:    %gp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 0
+; CHECK-NEXT:    store i32 48, ptr %gp_offset, align 4
+; CHECK-NEXT:    %fp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 1
+; CHECK-NEXT:    store i32 176, ptr %fp_offset, align 4
+; CHECK-NEXT:    %overfow_arg_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 2
+; CHECK-NEXT:    store ptr %vararg_buffer, ptr %overfow_arg_area, align 8
+; CHECK-NEXT:    %reg_save_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 3
+; CHECK-NEXT:    store ptr null, ptr %reg_save_area, align 8
+; CHECK-NEXT:    call void @wrapped(ptr %va_list) #8
+; CHECK-NEXT:    ret void
+;
+entry:
+  tail call void (...) @vararg(i32 noundef %x, ptr noundef nonnull byval(%struct.libcS) align 8 %y) #7
+  ret void
+}
+
+define dso_local void @libcS_i32(ptr noundef byval(%struct.libcS) align 8 %x, i32 noundef %y) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@libcS_i32(ptr noundef byval(%struct.libcS) align 8 %x, i32 noundef %y) local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %vararg_buffer = alloca %libcS_i32.vararg, align 8
+; CHECK-NEXT:    %0 = getelementptr inbounds %libcS_i32.vararg, ptr %vararg_buffer, i32 0, i32 0
+; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr %0, ptr %x, i64 32, i1 false)
+; CHECK-NEXT:    %1 = getelementptr inbounds %libcS_i32.vararg, ptr %vararg_buffer, i32 0, i32 1
+; CHECK-NEXT:    store i32 %y, ptr %1, align 4
+; CHECK-NEXT:    %va_list = alloca [1 x { i32, i32, ptr, ptr }], align 8
+; CHECK-NEXT:    %gp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 0
+; CHECK-NEXT:    store i32 48, ptr %gp_offset, align 4
+; CHECK-NEXT:    %fp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 1
+; CHECK-NEXT:    store i32 176, ptr %fp_offset, align 4
+; CHECK-NEXT:    %overfow_arg_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 2
+; CHECK-NEXT:    store ptr %vararg_buffer, ptr %overfow_arg_area, align 8
+; CHECK-NEXT:    %reg_save_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 3
+; CHECK-NEXT:    store ptr null, ptr %reg_save_area, align 8
+; CHECK-NEXT:    call void @wrapped(ptr %va_list) #8
+; CHECK-NEXT:    ret void
+;
+entry:
+  tail call void (...) @vararg(ptr noundef nonnull byval(%struct.libcS) align 8 %x, i32 noundef %y) #7
+  ret void
+}
+
+define dso_local void @i32_v4f32(i32 noundef %x, <4 x float> noundef %y) local_unnamed_addr #4 {
+; CHECK-LABEL: define {{[^@]+}}@i32_v4f32(i32 noundef %x, <4 x float> noundef %y) local_unnamed_addr #4 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %vararg_buffer = alloca %i32_v4f32.vararg, align 16
+; CHECK-NEXT:    %0 = getelementptr inbounds %i32_v4f32.vararg, ptr %vararg_buffer, i32 0, i32 0
+; CHECK-NEXT:    store i32 %x, ptr %0, align 4
+; CHECK-NEXT:    %1 = getelementptr inbounds %i32_v4f32.vararg, ptr %vararg_buffer, i32 0, i32 2
+; CHECK-NEXT:    store <4 x float> %y, ptr %1, align 16
+; CHECK-NEXT:    %va_list = alloca [1 x { i32, i32, ptr, ptr }], align 8
+; CHECK-NEXT:    %gp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 0
+; CHECK-NEXT:    store i32 48, ptr %gp_offset, align 4
+; CHECK-NEXT:    %fp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 1
+; CHECK-NEXT:    store i32 176, ptr %fp_offset, align 4
+; CHECK-NEXT:    %overfow_arg_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 2
+; CHECK-NEXT:    store ptr %vararg_buffer, ptr %overfow_arg_area, align 8
+; CHECK-NEXT:    %reg_save_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 3
+; CHECK-NEXT:    store ptr null, ptr %reg_save_area, align 8
+; CHECK-NEXT:    call void @wrapped(ptr %va_list) #8
+; CHECK-NEXT:    ret void
+;
+entry:
+  tail call void (...) @vararg(i32 noundef %x, <4 x float> noundef %y) #7
+  ret void
+}
+
+define dso_local void @v4f32_i32(<4 x float> noundef %x, i32 noundef %y) local_unnamed_addr #4 {
+; CHECK-LABEL: define {{[^@]+}}@v4f32_i32(<4 x float> noundef %x, i32 noundef %y) local_unnamed_addr #4 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %vararg_buffer = alloca %v4f32_i32.vararg, align 16
+; CHECK-NEXT:    %0 = getelementptr inbounds %v4f32_i32.vararg, ptr %vararg_buffer, i32 0, i32 0
+; CHECK-NEXT:    store <4 x float> %x, ptr %0, align 16
+; CHECK-NEXT:    %1 = getelementptr inbounds %v4f32_i32.vararg, ptr %vararg_buffer, i32 0, i32 1
+; CHECK-NEXT:    store i32 %y, ptr %1, align 4
+; CHECK-NEXT:    %va_list = alloca [1 x { i32, i32, ptr, ptr }], align 8
+; CHECK-NEXT:    %gp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 0
+; CHECK-NEXT:    store i32 48, ptr %gp_offset, align 4
+; CHECK-NEXT:    %fp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 1
+; CHECK-NEXT:    store i32 176, ptr %fp_offset, align 4
+; CHECK-NEXT:    %overfow_arg_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 2
+; CHECK-NEXT:    store ptr %vararg_buffer, ptr %overfow_arg_area, align 8
+; CHECK-NEXT:    %reg_save_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 3
+; CHECK-NEXT:    store ptr null, ptr %reg_save_area, align 8
+; CHECK-NEXT:    call void @wrapped(ptr %va_list) #8
+; CHECK-NEXT:    ret void
+;
+entry:
+  tail call void (...) @vararg(<4 x float> noundef %x, i32 noundef %y) #7
+  ret void
+}
+
+define dso_local void @i32_v8f32(i32 noundef %x, ptr nocapture noundef readonly byval(<8 x float>) align 32 %0) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@i32_v8f32(i32 noundef %x, ptr nocapture noundef readonly byval(<8 x float>) align 32 %0) local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %vararg_buffer = alloca %i32_v8f32.vararg, align 32
+; CHECK-NEXT:    %indirect-arg-temp = alloca <8 x float>, align 32
+; CHECK-NEXT:    %y = load <8 x float>, ptr %0, align 32, !tbaa !3
+; CHECK-NEXT:    store <8 x float> %y, ptr %indirect-arg-temp, align 32, !tbaa !3
+; CHECK-NEXT:    %1 = getelementptr inbounds %i32_v8f32.vararg, ptr %vararg_buffer, i32 0, i32 0
+; CHECK-NEXT:    store i32 %x, ptr %1, align 4
+; CHECK-NEXT:    %2 = getelementptr inbounds %i32_v8f32.vararg, ptr %vararg_buffer, i32 0, i32 2
+; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr %2, ptr %indirect-arg-temp, i64 32, i1 false)
+; CHECK-NEXT:    %va_list = alloca [1 x { i32, i32, ptr, ptr }], align 8
+; CHECK-NEXT:    %gp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 0
+; CHECK-NEXT:    store i32 48, ptr %gp_offset, align 4
+; CHECK-NEXT:    %fp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 1
+; CHECK-NEXT:    store i32 176, ptr %fp_offset, align 4
+; CHECK-NEXT:    %overfow_arg_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 2
+; CHECK-NEXT:    store ptr %vararg_buffer, ptr %overfow_arg_area, align 8
+; CHECK-NEXT:    %reg_save_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 3
+; CHECK-NEXT:    store ptr null, ptr %reg_save_area, align 8
+; CHECK-NEXT:    call void @wrapped(ptr %va_list) #8
+; CHECK-NEXT:    ret void
+;
+entry:
+  %indirect-arg-temp = alloca <8 x float>, align 32
+  %y = load <8 x float>, ptr %0, align 32, !tbaa !4
+  store <8 x float> %y, ptr %indirect-arg-temp, align 32, !tbaa !4
+  tail call void (...) @vararg(i32 noundef %x, ptr noundef nonnull byval(<8 x float>) align 32 %indirect-arg-temp) #7
+  ret void
+}
+
+define dso_local void @v8f32_i32(ptr nocapture noundef readonly byval(<8 x float>) align 32 %0, i32 noundef %y) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@v8f32_i32(ptr nocapture noundef readonly byval(<8 x float>) align 32 %0, i32 noundef %y) local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %vararg_buffer = alloca %v8f32_i32.vararg, align 32
+; CHECK-NEXT:    %indirect-arg-temp = alloca <8 x float>, align 32
+; CHECK-NEXT:    %x = load <8 x float>, ptr %0, align 32, !tbaa !3
+; CHECK-NEXT:    store <8 x float> %x, ptr %indirect-arg-temp, align 32, !tbaa !3
+; CHECK-NEXT:    %1 = getelementptr inbounds %v8f32_i32.vararg, ptr %vararg_buffer, i32 0, i32 0
+; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr %1, ptr %indirect-arg-temp, i64 32, i1 false)
+; CHECK-NEXT:    %2 = getelementptr inbounds %v8f32_i32.vararg, ptr %vararg_buffer, i32 0, i32 1
+; CHECK-NEXT:    store i32 %y, ptr %2, align 4
+; CHECK-NEXT:    %va_list = alloca [1 x { i32, i32, ptr, ptr }], align 8
+; CHECK-NEXT:    %gp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 0
+; CHECK-NEXT:    store i32 48, ptr %gp_offset, align 4
+; CHECK-NEXT:    %fp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 1
+; CHECK-NEXT:    store i32 176, ptr %fp_offset, align 4
+; CHECK-NEXT:    %overfow_arg_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 2
+; CHECK-NEXT:    store ptr %vararg_buffer, ptr %overfow_arg_area, align 8
+; CHECK-NEXT:    %reg_save_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 3
+; CHECK-NEXT:    store ptr null, ptr %reg_save_area, align 8
+; CHECK-NEXT:    call void @wrapped(ptr %va_list) #8
+; CHECK-NEXT:    ret void
+;
+entry:
+  %indirect-arg-temp = alloca <8 x float>, align 32
+  %x = load <8 x float>, ptr %0, align 32, !tbaa !4
+  store <8 x float> %x, ptr %indirect-arg-temp, align 32, !tbaa !4
+  tail call void (...) @vararg(ptr noundef nonnull byval(<8 x float>) align 32 %indirect-arg-temp, i32 noundef %y) #7
+  ret void
+}
+
+define dso_local void @i32_v16f32(i32 noundef %x, ptr nocapture noundef readonly byval(<16 x float>) align 64 %0) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@i32_v16f32(i32 noundef %x, ptr nocapture noundef readonly byval(<16 x float>) align 64 %0) local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %vararg_buffer = alloca %i32_v16f32.vararg, align 64
+; CHECK-NEXT:    %indirect-arg-temp = alloca <16 x float>, align 64
+; CHECK-NEXT:    %y = load <16 x float>, ptr %0, align 64, !tbaa !3
+; CHECK-NEXT:    store <16 x float> %y, ptr %indirect-arg-temp, align 64, !tbaa !3
+; CHECK-NEXT:    %1 = getelementptr inbounds %i32_v16f32.vararg, ptr %vararg_buffer, i32 0, i32 0
+; CHECK-NEXT:    store i32 %x, ptr %1, align 4
+; CHECK-NEXT:    %2 = getelementptr inbounds %i32_v16f32.vararg, ptr %vararg_buffer, i32 0, i32 2
+; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr %2, ptr %indirect-arg-temp, i64 64, i1 false)
+; CHECK-NEXT:    %va_list = alloca [1 x { i32, i32, ptr, ptr }], align 8
+; CHECK-NEXT:    %gp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 0
+; CHECK-NEXT:    store i32 48, ptr %gp_offset, align 4
+; CHECK-NEXT:    %fp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 1
+; CHECK-NEXT:    store i32 176, ptr %fp_offset, align 4
+; CHECK-NEXT:    %overfow_arg_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 2
+; CHECK-NEXT:    store ptr %vararg_buffer, ptr %overfow_arg_area, align 8
+; CHECK-NEXT:    %reg_save_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 3
+; CHECK-NEXT:    store ptr null, ptr %reg_save_area, align 8
+; CHECK-NEXT:    call void @wrapped(ptr %va_list) #8
+; CHECK-NEXT:    ret void
+;
+entry:
+  %indirect-arg-temp = alloca <16 x float>, align 64
+  %y = load <16 x float>, ptr %0, align 64, !tbaa !4
+  store <16 x float> %y, ptr %indirect-arg-temp, align 64, !tbaa !4
+  tail call void (...) @vararg(i32 noundef %x, ptr noundef nonnull byval(<16 x float>) align 64 %indirect-arg-temp) #7
+  ret void
+}
+
+define dso_local void @v16f32_i32(ptr nocapture noundef readonly byval(<16 x float>) align 64 %0, i32 noundef %y) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@v16f32_i32(ptr nocapture noundef readonly byval(<16 x float>) align 64 %0, i32 noundef %y) local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %vararg_buffer = alloca %v16f32_i32.vararg, align 64
+; CHECK-NEXT:    %indirect-arg-temp = alloca <16 x float>, align 64
+; CHECK-NEXT:    %x = load <16 x float>, ptr %0, align 64, !tbaa !3
+; CHECK-NEXT:    store <16 x float> %x, ptr %indirect-arg-temp, align 64, !tbaa !3
+; CHECK-NEXT:    %1 = getelementptr inbounds %v16f32_i32.vararg, ptr %vararg_buffer, i32 0, i32 0
+; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr %1, ptr %indirect-arg-temp, i64 64, i1 false)
+; CHECK-NEXT:    %2 = getelementptr inbounds %v16f32_i32.vararg, ptr %vararg_buffer, i32 0, i32 1
+; CHECK-NEXT:    store i32 %y, ptr %2, align 4
+; CHECK-NEXT:    %va_list = alloca [1 x { i32, i32, ptr, ptr }], align 8
+; CHECK-NEXT:    %gp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 0
+; CHECK-NEXT:    store i32 48, ptr %gp_offset, align 4
+; CHECK-NEXT:    %fp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 1
+; CHECK-NEXT:    store i32 176, ptr %fp_offset, align 4
+; CHECK-NEXT:    %overfow_arg_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 2
+; CHECK-NEXT:    store ptr %vararg_buffer, ptr %overfow_arg_area, align 8
+; CHECK-NEXT:    %reg_save_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 3
+; CHECK-NEXT:    store ptr null, ptr %reg_save_area, align 8
+; CHECK-NEXT:    call void @wrapped(ptr %va_list) #8
+; CHECK-NEXT:    ret void
+;
+entry:
+  %indirect-arg-temp = alloca <16 x float>, align 64
+  %x = load <16 x float>, ptr %0, align 64, !tbaa !4
+  store <16 x float> %x, ptr %indirect-arg-temp, align 64, !tbaa !4
+  tail call void (...) @vararg(ptr noundef nonnull byval(<16 x float>) align 64 %indirect-arg-temp, i32 noundef %y) #7
+  ret void
+}
+
+define dso_local void @i32_v32f32(i32 noundef %x, ptr nocapture noundef readonly byval(<32 x float>) align 128 %0) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@i32_v32f32(i32 noundef %x, ptr nocapture noundef readonly byval(<32 x float>) align 128 %0) local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %vararg_buffer = alloca %i32_v32f32.vararg, align 128
+; CHECK-NEXT:    %indirect-arg-temp = alloca <32 x float>, align 128
+; CHECK-NEXT:    %y = load <32 x float>, ptr %0, align 128, !tbaa !3
+; CHECK-NEXT:    store <32 x float> %y, ptr %indirect-arg-temp, align 128, !tbaa !3
+; CHECK-NEXT:    %1 = getelementptr inbounds %i32_v32f32.vararg, ptr %vararg_buffer, i32 0, i32 0
+; CHECK-NEXT:    store i32 %x, ptr %1, align 4
+; CHECK-NEXT:    %2 = getelementptr inbounds %i32_v32f32.vararg, ptr %vararg_buffer, i32 0, i32 2
+; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr %2, ptr %indirect-arg-temp, i64 128, i1 false)
+; CHECK-NEXT:    %va_list = alloca [1 x { i32, i32, ptr, ptr }], align 8
+; CHECK-NEXT:    %gp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 0
+; CHECK-NEXT:    store i32 48, ptr %gp_offset, align 4
+; CHECK-NEXT:    %fp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 1
+; CHECK-NEXT:    store i32 176, ptr %fp_offset, align 4
+; CHECK-NEXT:    %overfow_arg_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 2
+; CHECK-NEXT:    store ptr %vararg_buffer, ptr %overfow_arg_area, align 8
+; CHECK-NEXT:    %reg_save_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 3
+; CHECK-NEXT:    store ptr null, ptr %reg_save_area, align 8
+; CHECK-NEXT:    call void @wrapped(ptr %va_list) #8
+; CHECK-NEXT:    ret void
+;
+entry:
+  %indirect-arg-temp = alloca <32 x float>, align 128
+  %y = load <32 x float>, ptr %0, align 128, !tbaa !4
+  store <32 x float> %y, ptr %indirect-arg-temp, align 128, !tbaa !4
+  tail call void (...) @vararg(i32 noundef %x, ptr noundef nonnull byval(<32 x float>) align 128 %indirect-arg-temp) #7
+  ret void
+}
+
+define dso_local void @v32f32_i32(ptr nocapture noundef readonly byval(<32 x float>) align 128 %0, i32 noundef %y) local_unnamed_addr #0 {
+; CHECK-LABEL: define {{[^@]+}}@v32f32_i32(ptr nocapture noundef readonly byval(<32 x float>) align 128 %0, i32 noundef %y) local_unnamed_addr #0 {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    %vararg_buffer = alloca %v32f32_i32.vararg, align 128
+; CHECK-NEXT:    %indirect-arg-temp = alloca <32 x float>, align 128
+; CHECK-NEXT:    %x = load <32 x float>, ptr %0, align 128, !tbaa !3
+; CHECK-NEXT:    store <32 x float> %x, ptr %indirect-arg-temp, align 128, !tbaa !3
+; CHECK-NEXT:    %1 = getelementptr inbounds %v32f32_i32.vararg, ptr %vararg_buffer, i32 0, i32 0
+; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr %1, ptr %indirect-arg-temp, i64 128, i1 false)
+; CHECK-NEXT:    %2 = getelementptr inbounds %v32f32_i32.vararg, ptr %vararg_buffer, i32 0, i32 1
+; CHECK-NEXT:    store i32 %y, ptr %2, align 4
+; CHECK-NEXT:    %va_list = alloca [1 x { i32, i32, ptr, ptr }], align 8
+; CHECK-NEXT:    %gp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 0
+; CHECK-NEXT:    store i32 48, ptr %gp_offset, align 4
+; CHECK-NEXT:    %fp_offset = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 1
+; CHECK-NEXT:    store i32 176, ptr %fp_offset, align 4
+; CHECK-NEXT:    %overfow_arg_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 2
+; CHECK-NEXT:    store ptr %vararg_buffer, ptr %overfow_arg_area, align 8
+; CHECK-NEXT:    %reg_save_area = getelementptr inbounds [1 x { i32, i32, ptr, ptr }], ptr %va_list, i64 0, i32 0, i32 3
+; CHECK-NEXT:    store ptr null, ptr %reg_save_area, align 8
+; CHECK-NEXT:    call void @wrapped(ptr %va_list) #8
+; CHECK-NEXT:    ret void
+;
+entry:
+  %indirect-arg-temp = alloca <32 x float>, align 128
+  %x = load <32 x float>, ptr %0, align 128, !tbaa !4
+  store <32 x float> %x, ptr %indirect-arg-temp, align 128, !tbaa !4
+  tail call void (...) @vararg(ptr noundef nonnull byval(<32 x float>) align 128 %indirect-arg-temp, i32 noundef %y) #7
+  ret void
+}
+
+attributes #0 = { nounwind "min-legal-vector-width"="0" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #1 = { mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
+attributes #2 = { mustprogress nocallback nofree nosync nounwind willreturn }
+attributes #3 = { "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #4 = { nounwind "min-legal-vector-width"="128" "no-builtins" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+attributes #5 = { nounwind }
+attributes #6 = { nobuiltin nounwind "no-builtins" }
+attributes #7 = { nobuiltin "no-builtins" }
+
+!llvm.module.flags = !{!0, !1, !2}
----------------
JonChesterfield wrote:

Debug info is something I haven't really thought about. That's probably something that should have its own test case.

These are aspiring to show that the call frame is correct for the given architecture - variables are at the right offset and so forth - other things like metadata / attribute propagation are target independent and should have their own tests.

I'll look at removing the attributes from these, would give better signal to noise.

https://github.com/llvm/llvm-project/pull/81058


More information about the cfe-commits mailing list