[clang] 672e91e - clang: Add baseline test for nofpclass emission

Matt Arsenault via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 14 22:13:20 PDT 2023


Author: Matt Arsenault
Date: 2023-03-15T01:13:08-04:00
New Revision: 672e91ed982e157bdf609dc999dcdccb7f4e1234

URL: https://github.com/llvm/llvm-project/commit/672e91ed982e157bdf609dc999dcdccb7f4e1234
DIFF: https://github.com/llvm/llvm-project/commit/672e91ed982e157bdf609dc999dcdccb7f4e1234.diff

LOG: clang: Add baseline test for nofpclass emission

Added: 
    clang/test/CodeGen/nofpclass.c

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/clang/test/CodeGen/nofpclass.c b/clang/test/CodeGen/nofpclass.c
new file mode 100644
index 000000000000..d4fd7c92534d
--- /dev/null
+++ b/clang/test/CodeGen/nofpclass.c
@@ -0,0 +1,1437 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --check-attributes --version 2
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-feature +avx -fenable-matrix -ffinite-math-only -emit-llvm -o - %s | FileCheck -check-prefixes=CFINITEONLY %s
+// RUN: %clang_cc1 -x cl -triple x86_64-unknown-unknown -target-feature +avx -fenable-matrix -cl-finite-math-only -emit-llvm -o - %s | FileCheck -check-prefixes=CLFINITEONLY %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-feature +avx -fenable-matrix -menable-no-nans -emit-llvm -o - %s | FileCheck -check-prefixes=NONANS %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-feature +avx -fenable-matrix -menable-no-infs -emit-llvm -o - %s | FileCheck -check-prefixes=NOINFS %s
+
+// XUN: %clang_cc1 -triple x86_64-unknown-unknown -target-feature +avx -fenable-matrix -fsignaling-nans -emit-llvm -o - %s | FileCheck -check-prefixes=SNANS %s
+// XUN: %clang_cc1 -triple x86_64-unknown-unknown -target-feature +avx -fenable-matrix -fno-signaling-nans -emit-llvm -o - %s | FileCheck -check-prefixes=NO-SNANS %s
+
+#ifdef __OPENCL_C_VERSION__
+#pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
+#endif
+
+typedef float float1 __attribute__((ext_vector_type(1)));
+typedef float float2 __attribute__((ext_vector_type(2)));
+typedef _Float16 half2 __attribute__((ext_vector_type(2)));
+typedef double double2 __attribute__((ext_vector_type(2)));
+typedef double dx5x5_t __attribute__((matrix_type(5, 5)));
+
+extern float extern_func(float, double, _Float16);
+extern float2 extern_func_vec(float2, double2, half2);
+extern _Complex float extern_complex(_Complex float, _Complex double, _Complex _Float16);
+extern float variadic(float, ...);
+extern dx5x5_t extern_matrix(dx5x5_t);
+
+
+// CFINITEONLY: Function Attrs: noinline nounwind optnone
+// CFINITEONLY-LABEL: define dso_local float @defined_func_f32
+// CFINITEONLY-SAME: (float noundef [[A:%.*]], float noundef [[B:%.*]], float noundef [[C:%.*]]) #[[ATTR0:[0-9]+]] {
+// CFINITEONLY-NEXT:  entry:
+// CFINITEONLY-NEXT:    [[A_ADDR:%.*]] = alloca float, align 4
+// CFINITEONLY-NEXT:    [[B_ADDR:%.*]] = alloca float, align 4
+// CFINITEONLY-NEXT:    [[C_ADDR:%.*]] = alloca float, align 4
+// CFINITEONLY-NEXT:    store float [[A]], ptr [[A_ADDR]], align 4
+// CFINITEONLY-NEXT:    store float [[B]], ptr [[B_ADDR]], align 4
+// CFINITEONLY-NEXT:    store float [[C]], ptr [[C_ADDR]], align 4
+// CFINITEONLY-NEXT:    [[TMP0:%.*]] = load float, ptr [[A_ADDR]], align 4
+// CFINITEONLY-NEXT:    [[TMP1:%.*]] = load float, ptr [[B_ADDR]], align 4
+// CFINITEONLY-NEXT:    [[TMP2:%.*]] = load float, ptr [[C_ADDR]], align 4
+// CFINITEONLY-NEXT:    [[TMP3:%.*]] = call nnan ninf float @llvm.fma.f32(float [[TMP0]], float [[TMP1]], float [[TMP2]])
+// CFINITEONLY-NEXT:    [[ADD:%.*]] = fadd nnan ninf float [[TMP3]], 4.000000e+00
+// CFINITEONLY-NEXT:    ret float [[ADD]]
+//
+// CLFINITEONLY: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
+// CLFINITEONLY-LABEL: define dso_local float @defined_func_f32
+// CLFINITEONLY-SAME: (float noundef [[A:%.*]], float noundef [[B:%.*]], float noundef [[C:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// CLFINITEONLY-NEXT:  entry:
+// CLFINITEONLY-NEXT:    [[TMP0:%.*]] = tail call nnan ninf float @llvm.fma.f32(float [[A]], float [[B]], float [[C]])
+// CLFINITEONLY-NEXT:    [[ADD:%.*]] = fadd nnan ninf float [[TMP0]], 4.000000e+00
+// CLFINITEONLY-NEXT:    ret float [[ADD]]
+//
+// NONANS: Function Attrs: noinline nounwind optnone
+// NONANS-LABEL: define dso_local float @defined_func_f32
+// NONANS-SAME: (float noundef [[A:%.*]], float noundef [[B:%.*]], float noundef [[C:%.*]]) #[[ATTR0:[0-9]+]] {
+// NONANS-NEXT:  entry:
+// NONANS-NEXT:    [[A_ADDR:%.*]] = alloca float, align 4
+// NONANS-NEXT:    [[B_ADDR:%.*]] = alloca float, align 4
+// NONANS-NEXT:    [[C_ADDR:%.*]] = alloca float, align 4
+// NONANS-NEXT:    store float [[A]], ptr [[A_ADDR]], align 4
+// NONANS-NEXT:    store float [[B]], ptr [[B_ADDR]], align 4
+// NONANS-NEXT:    store float [[C]], ptr [[C_ADDR]], align 4
+// NONANS-NEXT:    [[TMP0:%.*]] = load float, ptr [[A_ADDR]], align 4
+// NONANS-NEXT:    [[TMP1:%.*]] = load float, ptr [[B_ADDR]], align 4
+// NONANS-NEXT:    [[TMP2:%.*]] = load float, ptr [[C_ADDR]], align 4
+// NONANS-NEXT:    [[TMP3:%.*]] = call nnan float @llvm.fma.f32(float [[TMP0]], float [[TMP1]], float [[TMP2]])
+// NONANS-NEXT:    [[ADD:%.*]] = fadd nnan float [[TMP3]], 4.000000e+00
+// NONANS-NEXT:    ret float [[ADD]]
+//
+// NOINFS: Function Attrs: noinline nounwind optnone
+// NOINFS-LABEL: define dso_local float @defined_func_f32
+// NOINFS-SAME: (float noundef [[A:%.*]], float noundef [[B:%.*]], float noundef [[C:%.*]]) #[[ATTR0:[0-9]+]] {
+// NOINFS-NEXT:  entry:
+// NOINFS-NEXT:    [[A_ADDR:%.*]] = alloca float, align 4
+// NOINFS-NEXT:    [[B_ADDR:%.*]] = alloca float, align 4
+// NOINFS-NEXT:    [[C_ADDR:%.*]] = alloca float, align 4
+// NOINFS-NEXT:    store float [[A]], ptr [[A_ADDR]], align 4
+// NOINFS-NEXT:    store float [[B]], ptr [[B_ADDR]], align 4
+// NOINFS-NEXT:    store float [[C]], ptr [[C_ADDR]], align 4
+// NOINFS-NEXT:    [[TMP0:%.*]] = load float, ptr [[A_ADDR]], align 4
+// NOINFS-NEXT:    [[TMP1:%.*]] = load float, ptr [[B_ADDR]], align 4
+// NOINFS-NEXT:    [[TMP2:%.*]] = load float, ptr [[C_ADDR]], align 4
+// NOINFS-NEXT:    [[TMP3:%.*]] = call ninf float @llvm.fma.f32(float [[TMP0]], float [[TMP1]], float [[TMP2]])
+// NOINFS-NEXT:    [[ADD:%.*]] = fadd ninf float [[TMP3]], 4.000000e+00
+// NOINFS-NEXT:    ret float [[ADD]]
+//
+float defined_func_f32(float a, float b, float c) {
+  return __builtin_fmaf(a, b, c) + 4.0f;
+}
+
+// CFINITEONLY: Function Attrs: noinline nounwind optnone
+// CFINITEONLY-LABEL: define dso_local <2 x double> @defined_func_v2f64
+// CFINITEONLY-SAME: (<2 x double> noundef [[A:%.*]], <2 x double> noundef [[B:%.*]], <2 x double> noundef [[C:%.*]]) #[[ATTR2:[0-9]+]] {
+// CFINITEONLY-NEXT:  entry:
+// CFINITEONLY-NEXT:    [[A_ADDR:%.*]] = alloca <2 x double>, align 16
+// CFINITEONLY-NEXT:    [[B_ADDR:%.*]] = alloca <2 x double>, align 16
+// CFINITEONLY-NEXT:    [[C_ADDR:%.*]] = alloca <2 x double>, align 16
+// CFINITEONLY-NEXT:    store <2 x double> [[A]], ptr [[A_ADDR]], align 16
+// CFINITEONLY-NEXT:    store <2 x double> [[B]], ptr [[B_ADDR]], align 16
+// CFINITEONLY-NEXT:    store <2 x double> [[C]], ptr [[C_ADDR]], align 16
+// CFINITEONLY-NEXT:    [[TMP0:%.*]] = load <2 x double>, ptr [[A_ADDR]], align 16
+// CFINITEONLY-NEXT:    [[TMP1:%.*]] = load <2 x double>, ptr [[B_ADDR]], align 16
+// CFINITEONLY-NEXT:    [[TMP2:%.*]] = load <2 x double>, ptr [[C_ADDR]], align 16
+// CFINITEONLY-NEXT:    [[TMP3:%.*]] = call nnan ninf <2 x double> @llvm.fma.v2f64(<2 x double> [[TMP0]], <2 x double> [[TMP1]], <2 x double> [[TMP2]])
+// CFINITEONLY-NEXT:    [[ADD:%.*]] = fadd nnan ninf <2 x double> [[TMP3]], <double 4.000000e+00, double 4.000000e+00>
+// CFINITEONLY-NEXT:    ret <2 x double> [[ADD]]
+//
+// CLFINITEONLY: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
+// CLFINITEONLY-LABEL: define dso_local <2 x double> @defined_func_v2f64
+// CLFINITEONLY-SAME: (<2 x double> noundef [[A:%.*]], <2 x double> noundef [[B:%.*]], <2 x double> noundef [[C:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {
+// CLFINITEONLY-NEXT:  entry:
+// CLFINITEONLY-NEXT:    [[TMP0:%.*]] = tail call nnan ninf <2 x double> @llvm.fma.v2f64(<2 x double> [[A]], <2 x double> [[B]], <2 x double> [[C]])
+// CLFINITEONLY-NEXT:    [[ADD:%.*]] = fadd nnan ninf <2 x double> [[TMP0]], <double 4.000000e+00, double 4.000000e+00>
+// CLFINITEONLY-NEXT:    ret <2 x double> [[ADD]]
+//
+// NONANS: Function Attrs: noinline nounwind optnone
+// NONANS-LABEL: define dso_local <2 x double> @defined_func_v2f64
+// NONANS-SAME: (<2 x double> noundef [[A:%.*]], <2 x double> noundef [[B:%.*]], <2 x double> noundef [[C:%.*]]) #[[ATTR2:[0-9]+]] {
+// NONANS-NEXT:  entry:
+// NONANS-NEXT:    [[A_ADDR:%.*]] = alloca <2 x double>, align 16
+// NONANS-NEXT:    [[B_ADDR:%.*]] = alloca <2 x double>, align 16
+// NONANS-NEXT:    [[C_ADDR:%.*]] = alloca <2 x double>, align 16
+// NONANS-NEXT:    store <2 x double> [[A]], ptr [[A_ADDR]], align 16
+// NONANS-NEXT:    store <2 x double> [[B]], ptr [[B_ADDR]], align 16
+// NONANS-NEXT:    store <2 x double> [[C]], ptr [[C_ADDR]], align 16
+// NONANS-NEXT:    [[TMP0:%.*]] = load <2 x double>, ptr [[A_ADDR]], align 16
+// NONANS-NEXT:    [[TMP1:%.*]] = load <2 x double>, ptr [[B_ADDR]], align 16
+// NONANS-NEXT:    [[TMP2:%.*]] = load <2 x double>, ptr [[C_ADDR]], align 16
+// NONANS-NEXT:    [[TMP3:%.*]] = call nnan <2 x double> @llvm.fma.v2f64(<2 x double> [[TMP0]], <2 x double> [[TMP1]], <2 x double> [[TMP2]])
+// NONANS-NEXT:    [[ADD:%.*]] = fadd nnan <2 x double> [[TMP3]], <double 4.000000e+00, double 4.000000e+00>
+// NONANS-NEXT:    ret <2 x double> [[ADD]]
+//
+// NOINFS: Function Attrs: noinline nounwind optnone
+// NOINFS-LABEL: define dso_local <2 x double> @defined_func_v2f64
+// NOINFS-SAME: (<2 x double> noundef [[A:%.*]], <2 x double> noundef [[B:%.*]], <2 x double> noundef [[C:%.*]]) #[[ATTR2:[0-9]+]] {
+// NOINFS-NEXT:  entry:
+// NOINFS-NEXT:    [[A_ADDR:%.*]] = alloca <2 x double>, align 16
+// NOINFS-NEXT:    [[B_ADDR:%.*]] = alloca <2 x double>, align 16
+// NOINFS-NEXT:    [[C_ADDR:%.*]] = alloca <2 x double>, align 16
+// NOINFS-NEXT:    store <2 x double> [[A]], ptr [[A_ADDR]], align 16
+// NOINFS-NEXT:    store <2 x double> [[B]], ptr [[B_ADDR]], align 16
+// NOINFS-NEXT:    store <2 x double> [[C]], ptr [[C_ADDR]], align 16
+// NOINFS-NEXT:    [[TMP0:%.*]] = load <2 x double>, ptr [[A_ADDR]], align 16
+// NOINFS-NEXT:    [[TMP1:%.*]] = load <2 x double>, ptr [[B_ADDR]], align 16
+// NOINFS-NEXT:    [[TMP2:%.*]] = load <2 x double>, ptr [[C_ADDR]], align 16
+// NOINFS-NEXT:    [[TMP3:%.*]] = call ninf <2 x double> @llvm.fma.v2f64(<2 x double> [[TMP0]], <2 x double> [[TMP1]], <2 x double> [[TMP2]])
+// NOINFS-NEXT:    [[ADD:%.*]] = fadd ninf <2 x double> [[TMP3]], <double 4.000000e+00, double 4.000000e+00>
+// NOINFS-NEXT:    ret <2 x double> [[ADD]]
+//
+double2 defined_func_v2f64(double2 a, double2 b, double2 c) {
+  return __builtin_elementwise_fma(a, b, c) + 4.0;
+}
+
+// CFINITEONLY: Function Attrs: noinline nounwind optnone
+// CFINITEONLY-LABEL: define dso_local float @call_extern_func
+// CFINITEONLY-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], half noundef [[C:%.*]]) #[[ATTR0]] {
+// CFINITEONLY-NEXT:  entry:
+// CFINITEONLY-NEXT:    [[A_ADDR:%.*]] = alloca float, align 4
+// CFINITEONLY-NEXT:    [[B_ADDR:%.*]] = alloca double, align 8
+// CFINITEONLY-NEXT:    [[C_ADDR:%.*]] = alloca half, align 2
+// CFINITEONLY-NEXT:    store float [[A]], ptr [[A_ADDR]], align 4
+// CFINITEONLY-NEXT:    store double [[B]], ptr [[B_ADDR]], align 8
+// CFINITEONLY-NEXT:    store half [[C]], ptr [[C_ADDR]], align 2
+// CFINITEONLY-NEXT:    [[TMP0:%.*]] = load float, ptr [[A_ADDR]], align 4
+// CFINITEONLY-NEXT:    [[TMP1:%.*]] = load double, ptr [[B_ADDR]], align 8
+// CFINITEONLY-NEXT:    [[TMP2:%.*]] = load half, ptr [[C_ADDR]], align 2
+// CFINITEONLY-NEXT:    [[CALL:%.*]] = call nnan ninf float @extern_func(float noundef [[TMP0]], double noundef [[TMP1]], half noundef [[TMP2]])
+// CFINITEONLY-NEXT:    ret float [[CALL]]
+//
+// CLFINITEONLY: Function Attrs: convergent norecurse nounwind
+// CLFINITEONLY-LABEL: define dso_local float @call_extern_func
+// CLFINITEONLY-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], half noundef [[C:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
+// CLFINITEONLY-NEXT:  entry:
+// CLFINITEONLY-NEXT:    [[CALL:%.*]] = tail call nnan ninf float @extern_func(float noundef [[A]], double noundef [[B]], half noundef [[C]]) #[[ATTR10:[0-9]+]]
+// CLFINITEONLY-NEXT:    ret float [[CALL]]
+//
+// NONANS: Function Attrs: noinline nounwind optnone
+// NONANS-LABEL: define dso_local float @call_extern_func
+// NONANS-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], half noundef [[C:%.*]]) #[[ATTR0]] {
+// NONANS-NEXT:  entry:
+// NONANS-NEXT:    [[A_ADDR:%.*]] = alloca float, align 4
+// NONANS-NEXT:    [[B_ADDR:%.*]] = alloca double, align 8
+// NONANS-NEXT:    [[C_ADDR:%.*]] = alloca half, align 2
+// NONANS-NEXT:    store float [[A]], ptr [[A_ADDR]], align 4
+// NONANS-NEXT:    store double [[B]], ptr [[B_ADDR]], align 8
+// NONANS-NEXT:    store half [[C]], ptr [[C_ADDR]], align 2
+// NONANS-NEXT:    [[TMP0:%.*]] = load float, ptr [[A_ADDR]], align 4
+// NONANS-NEXT:    [[TMP1:%.*]] = load double, ptr [[B_ADDR]], align 8
+// NONANS-NEXT:    [[TMP2:%.*]] = load half, ptr [[C_ADDR]], align 2
+// NONANS-NEXT:    [[CALL:%.*]] = call nnan float @extern_func(float noundef [[TMP0]], double noundef [[TMP1]], half noundef [[TMP2]])
+// NONANS-NEXT:    ret float [[CALL]]
+//
+// NOINFS: Function Attrs: noinline nounwind optnone
+// NOINFS-LABEL: define dso_local float @call_extern_func
+// NOINFS-SAME: (float noundef [[A:%.*]], double noundef [[B:%.*]], half noundef [[C:%.*]]) #[[ATTR0]] {
+// NOINFS-NEXT:  entry:
+// NOINFS-NEXT:    [[A_ADDR:%.*]] = alloca float, align 4
+// NOINFS-NEXT:    [[B_ADDR:%.*]] = alloca double, align 8
+// NOINFS-NEXT:    [[C_ADDR:%.*]] = alloca half, align 2
+// NOINFS-NEXT:    store float [[A]], ptr [[A_ADDR]], align 4
+// NOINFS-NEXT:    store double [[B]], ptr [[B_ADDR]], align 8
+// NOINFS-NEXT:    store half [[C]], ptr [[C_ADDR]], align 2
+// NOINFS-NEXT:    [[TMP0:%.*]] = load float, ptr [[A_ADDR]], align 4
+// NOINFS-NEXT:    [[TMP1:%.*]] = load double, ptr [[B_ADDR]], align 8
+// NOINFS-NEXT:    [[TMP2:%.*]] = load half, ptr [[C_ADDR]], align 2
+// NOINFS-NEXT:    [[CALL:%.*]] = call ninf float @extern_func(float noundef [[TMP0]], double noundef [[TMP1]], half noundef [[TMP2]])
+// NOINFS-NEXT:    ret float [[CALL]]
+//
+float call_extern_func(float a, double b, _Float16 c) {
+  return extern_func(a, b, c);
+}
+
+// CFINITEONLY: Function Attrs: noinline nounwind optnone
+// CFINITEONLY-LABEL: define dso_local double @call_extern_func_vec
+// CFINITEONLY-SAME: (double noundef [[A_COERCE:%.*]], <2 x double> noundef [[B:%.*]], i32 noundef [[C_COERCE:%.*]]) #[[ATTR2]] {
+// CFINITEONLY-NEXT:  entry:
+// CFINITEONLY-NEXT:    [[RETVAL:%.*]] = alloca <2 x float>, align 8
+// CFINITEONLY-NEXT:    [[A:%.*]] = alloca <2 x float>, align 8
+// CFINITEONLY-NEXT:    [[C:%.*]] = alloca <2 x half>, align 4
+// CFINITEONLY-NEXT:    [[A_ADDR:%.*]] = alloca <2 x float>, align 8
+// CFINITEONLY-NEXT:    [[B_ADDR:%.*]] = alloca <2 x double>, align 16
+// CFINITEONLY-NEXT:    [[C_ADDR:%.*]] = alloca <2 x half>, align 4
+// CFINITEONLY-NEXT:    [[COERCE:%.*]] = alloca <2 x float>, align 8
+// CFINITEONLY-NEXT:    [[COERCE3:%.*]] = alloca <2 x half>, align 4
+// CFINITEONLY-NEXT:    [[COERCE4:%.*]] = alloca <2 x float>, align 8
+// CFINITEONLY-NEXT:    store double [[A_COERCE]], ptr [[A]], align 8
+// CFINITEONLY-NEXT:    [[A1:%.*]] = load <2 x float>, ptr [[A]], align 8
+// CFINITEONLY-NEXT:    store i32 [[C_COERCE]], ptr [[C]], align 4
+// CFINITEONLY-NEXT:    [[C2:%.*]] = load <2 x half>, ptr [[C]], align 4
+// CFINITEONLY-NEXT:    store <2 x float> [[A1]], ptr [[A_ADDR]], align 8
+// CFINITEONLY-NEXT:    store <2 x double> [[B]], ptr [[B_ADDR]], align 16
+// CFINITEONLY-NEXT:    store <2 x half> [[C2]], ptr [[C_ADDR]], align 4
+// CFINITEONLY-NEXT:    [[TMP0:%.*]] = load <2 x float>, ptr [[A_ADDR]], align 8
+// CFINITEONLY-NEXT:    [[TMP1:%.*]] = load <2 x double>, ptr [[B_ADDR]], align 16
+// CFINITEONLY-NEXT:    [[TMP2:%.*]] = load <2 x half>, ptr [[C_ADDR]], align 4
+// CFINITEONLY-NEXT:    store <2 x float> [[TMP0]], ptr [[COERCE]], align 8
+// CFINITEONLY-NEXT:    [[TMP3:%.*]] = load double, ptr [[COERCE]], align 8
+// CFINITEONLY-NEXT:    store <2 x half> [[TMP2]], ptr [[COERCE3]], align 4
+// CFINITEONLY-NEXT:    [[TMP4:%.*]] = load i32, ptr [[COERCE3]], align 4
+// CFINITEONLY-NEXT:    [[CALL:%.*]] = call nnan ninf double @extern_func_vec(double noundef [[TMP3]], <2 x double> noundef [[TMP1]], i32 noundef [[TMP4]])
+// CFINITEONLY-NEXT:    store double [[CALL]], ptr [[COERCE4]], align 8
+// CFINITEONLY-NEXT:    [[TMP5:%.*]] = load <2 x float>, ptr [[COERCE4]], align 8
+// CFINITEONLY-NEXT:    store <2 x float> [[TMP5]], ptr [[RETVAL]], align 8
+// CFINITEONLY-NEXT:    [[TMP6:%.*]] = load double, ptr [[RETVAL]], align 8
+// CFINITEONLY-NEXT:    ret double [[TMP6]]
+//
+// CLFINITEONLY: Function Attrs: convergent norecurse nounwind
+// CLFINITEONLY-LABEL: define dso_local double @call_extern_func_vec
+// CLFINITEONLY-SAME: (double noundef [[A_COERCE:%.*]], <2 x double> noundef [[B:%.*]], i32 noundef [[C_COERCE:%.*]]) local_unnamed_addr #[[ATTR5:[0-9]+]] {
+// CLFINITEONLY-NEXT:  entry:
+// CLFINITEONLY-NEXT:    [[CALL:%.*]] = tail call nnan ninf double @extern_func_vec(double noundef [[A_COERCE]], <2 x double> noundef [[B]], i32 noundef [[C_COERCE]]) #[[ATTR10]]
+// CLFINITEONLY-NEXT:    ret double [[CALL]]
+//
+// NONANS: Function Attrs: noinline nounwind optnone
+// NONANS-LABEL: define dso_local double @call_extern_func_vec
+// NONANS-SAME: (double noundef [[A_COERCE:%.*]], <2 x double> noundef [[B:%.*]], i32 noundef [[C_COERCE:%.*]]) #[[ATTR2]] {
+// NONANS-NEXT:  entry:
+// NONANS-NEXT:    [[RETVAL:%.*]] = alloca <2 x float>, align 8
+// NONANS-NEXT:    [[A:%.*]] = alloca <2 x float>, align 8
+// NONANS-NEXT:    [[C:%.*]] = alloca <2 x half>, align 4
+// NONANS-NEXT:    [[A_ADDR:%.*]] = alloca <2 x float>, align 8
+// NONANS-NEXT:    [[B_ADDR:%.*]] = alloca <2 x double>, align 16
+// NONANS-NEXT:    [[C_ADDR:%.*]] = alloca <2 x half>, align 4
+// NONANS-NEXT:    [[COERCE:%.*]] = alloca <2 x float>, align 8
+// NONANS-NEXT:    [[COERCE3:%.*]] = alloca <2 x half>, align 4
+// NONANS-NEXT:    [[COERCE4:%.*]] = alloca <2 x float>, align 8
+// NONANS-NEXT:    store double [[A_COERCE]], ptr [[A]], align 8
+// NONANS-NEXT:    [[A1:%.*]] = load <2 x float>, ptr [[A]], align 8
+// NONANS-NEXT:    store i32 [[C_COERCE]], ptr [[C]], align 4
+// NONANS-NEXT:    [[C2:%.*]] = load <2 x half>, ptr [[C]], align 4
+// NONANS-NEXT:    store <2 x float> [[A1]], ptr [[A_ADDR]], align 8
+// NONANS-NEXT:    store <2 x double> [[B]], ptr [[B_ADDR]], align 16
+// NONANS-NEXT:    store <2 x half> [[C2]], ptr [[C_ADDR]], align 4
+// NONANS-NEXT:    [[TMP0:%.*]] = load <2 x float>, ptr [[A_ADDR]], align 8
+// NONANS-NEXT:    [[TMP1:%.*]] = load <2 x double>, ptr [[B_ADDR]], align 16
+// NONANS-NEXT:    [[TMP2:%.*]] = load <2 x half>, ptr [[C_ADDR]], align 4
+// NONANS-NEXT:    store <2 x float> [[TMP0]], ptr [[COERCE]], align 8
+// NONANS-NEXT:    [[TMP3:%.*]] = load double, ptr [[COERCE]], align 8
+// NONANS-NEXT:    store <2 x half> [[TMP2]], ptr [[COERCE3]], align 4
+// NONANS-NEXT:    [[TMP4:%.*]] = load i32, ptr [[COERCE3]], align 4
+// NONANS-NEXT:    [[CALL:%.*]] = call nnan double @extern_func_vec(double noundef [[TMP3]], <2 x double> noundef [[TMP1]], i32 noundef [[TMP4]])
+// NONANS-NEXT:    store double [[CALL]], ptr [[COERCE4]], align 8
+// NONANS-NEXT:    [[TMP5:%.*]] = load <2 x float>, ptr [[COERCE4]], align 8
+// NONANS-NEXT:    store <2 x float> [[TMP5]], ptr [[RETVAL]], align 8
+// NONANS-NEXT:    [[TMP6:%.*]] = load double, ptr [[RETVAL]], align 8
+// NONANS-NEXT:    ret double [[TMP6]]
+//
+// NOINFS: Function Attrs: noinline nounwind optnone
+// NOINFS-LABEL: define dso_local double @call_extern_func_vec
+// NOINFS-SAME: (double noundef [[A_COERCE:%.*]], <2 x double> noundef [[B:%.*]], i32 noundef [[C_COERCE:%.*]]) #[[ATTR2]] {
+// NOINFS-NEXT:  entry:
+// NOINFS-NEXT:    [[RETVAL:%.*]] = alloca <2 x float>, align 8
+// NOINFS-NEXT:    [[A:%.*]] = alloca <2 x float>, align 8
+// NOINFS-NEXT:    [[C:%.*]] = alloca <2 x half>, align 4
+// NOINFS-NEXT:    [[A_ADDR:%.*]] = alloca <2 x float>, align 8
+// NOINFS-NEXT:    [[B_ADDR:%.*]] = alloca <2 x double>, align 16
+// NOINFS-NEXT:    [[C_ADDR:%.*]] = alloca <2 x half>, align 4
+// NOINFS-NEXT:    [[COERCE:%.*]] = alloca <2 x float>, align 8
+// NOINFS-NEXT:    [[COERCE3:%.*]] = alloca <2 x half>, align 4
+// NOINFS-NEXT:    [[COERCE4:%.*]] = alloca <2 x float>, align 8
+// NOINFS-NEXT:    store double [[A_COERCE]], ptr [[A]], align 8
+// NOINFS-NEXT:    [[A1:%.*]] = load <2 x float>, ptr [[A]], align 8
+// NOINFS-NEXT:    store i32 [[C_COERCE]], ptr [[C]], align 4
+// NOINFS-NEXT:    [[C2:%.*]] = load <2 x half>, ptr [[C]], align 4
+// NOINFS-NEXT:    store <2 x float> [[A1]], ptr [[A_ADDR]], align 8
+// NOINFS-NEXT:    store <2 x double> [[B]], ptr [[B_ADDR]], align 16
+// NOINFS-NEXT:    store <2 x half> [[C2]], ptr [[C_ADDR]], align 4
+// NOINFS-NEXT:    [[TMP0:%.*]] = load <2 x float>, ptr [[A_ADDR]], align 8
+// NOINFS-NEXT:    [[TMP1:%.*]] = load <2 x double>, ptr [[B_ADDR]], align 16
+// NOINFS-NEXT:    [[TMP2:%.*]] = load <2 x half>, ptr [[C_ADDR]], align 4
+// NOINFS-NEXT:    store <2 x float> [[TMP0]], ptr [[COERCE]], align 8
+// NOINFS-NEXT:    [[TMP3:%.*]] = load double, ptr [[COERCE]], align 8
+// NOINFS-NEXT:    store <2 x half> [[TMP2]], ptr [[COERCE3]], align 4
+// NOINFS-NEXT:    [[TMP4:%.*]] = load i32, ptr [[COERCE3]], align 4
+// NOINFS-NEXT:    [[CALL:%.*]] = call ninf double @extern_func_vec(double noundef [[TMP3]], <2 x double> noundef [[TMP1]], i32 noundef [[TMP4]])
+// NOINFS-NEXT:    store double [[CALL]], ptr [[COERCE4]], align 8
+// NOINFS-NEXT:    [[TMP5:%.*]] = load <2 x float>, ptr [[COERCE4]], align 8
+// NOINFS-NEXT:    store <2 x float> [[TMP5]], ptr [[RETVAL]], align 8
+// NOINFS-NEXT:    [[TMP6:%.*]] = load double, ptr [[RETVAL]], align 8
+// NOINFS-NEXT:    ret double [[TMP6]]
+//
+float2 call_extern_func_vec(float2 a, double2 b, half2 c) {
+  return extern_func_vec(a, b, c);
+}
+
+// CFINITEONLY: Function Attrs: noinline nounwind optnone
+// CFINITEONLY-LABEL: define dso_local <2 x float> @defined_complex_func
+// CFINITEONLY-SAME: (<2 x float> noundef [[A_COERCE:%.*]], double noundef [[B_COERCE0:%.*]], double noundef [[B_COERCE1:%.*]], <2 x half> noundef [[C_COERCE:%.*]]) #[[ATTR4:[0-9]+]] {
+// CFINITEONLY-NEXT:  entry:
+// CFINITEONLY-NEXT:    [[RETVAL:%.*]] = alloca { float, float }, align 4
+// CFINITEONLY-NEXT:    [[A:%.*]] = alloca { float, float }, align 4
+// CFINITEONLY-NEXT:    [[B:%.*]] = alloca { double, double }, align 8
+// CFINITEONLY-NEXT:    [[C:%.*]] = alloca { half, half }, align 2
+// CFINITEONLY-NEXT:    [[COERCE:%.*]] = alloca { float, float }, align 4
+// CFINITEONLY-NEXT:    [[COERCE1:%.*]] = alloca { double, double }, align 8
+// CFINITEONLY-NEXT:    [[COERCE2:%.*]] = alloca { half, half }, align 2
+// CFINITEONLY-NEXT:    [[COERCE3:%.*]] = alloca { float, float }, align 4
+// CFINITEONLY-NEXT:    store <2 x float> [[A_COERCE]], ptr [[A]], align 4
+// CFINITEONLY-NEXT:    [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0
+// CFINITEONLY-NEXT:    store double [[B_COERCE0]], ptr [[TMP0]], align 8
+// CFINITEONLY-NEXT:    [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1
+// CFINITEONLY-NEXT:    store double [[B_COERCE1]], ptr [[TMP1]], align 8
+// CFINITEONLY-NEXT:    store <2 x half> [[C_COERCE]], ptr [[C]], align 2
+// CFINITEONLY-NEXT:    [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4
+// CFINITEONLY-NEXT:    [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1
+// CFINITEONLY-NEXT:    [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4
+// CFINITEONLY-NEXT:    [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8
+// CFINITEONLY-NEXT:    [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1
+// CFINITEONLY-NEXT:    [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8
+// CFINITEONLY-NEXT:    [[C_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2
+// CFINITEONLY-NEXT:    [[C_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 1
+// CFINITEONLY-NEXT:    [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2
+// CFINITEONLY-NEXT:    [[COERCE_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[COERCE_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 1
+// CFINITEONLY-NEXT:    store float [[A_REAL]], ptr [[COERCE_REALP]], align 4
+// CFINITEONLY-NEXT:    store float [[A_IMAG]], ptr [[COERCE_IMAGP]], align 4
+// CFINITEONLY-NEXT:    [[TMP2:%.*]] = load <2 x float>, ptr [[COERCE]], align 4
+// CFINITEONLY-NEXT:    [[COERCE1_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[COERCE1]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[COERCE1_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[COERCE1]], i32 0, i32 1
+// CFINITEONLY-NEXT:    store double [[B_REAL]], ptr [[COERCE1_REALP]], align 8
+// CFINITEONLY-NEXT:    store double [[B_IMAG]], ptr [[COERCE1_IMAGP]], align 8
+// CFINITEONLY-NEXT:    [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[COERCE1]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[TMP4:%.*]] = load double, ptr [[TMP3]], align 8
+// CFINITEONLY-NEXT:    [[TMP5:%.*]] = getelementptr inbounds { double, double }, ptr [[COERCE1]], i32 0, i32 1
+// CFINITEONLY-NEXT:    [[TMP6:%.*]] = load double, ptr [[TMP5]], align 8
+// CFINITEONLY-NEXT:    [[COERCE2_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[COERCE2]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[COERCE2_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[COERCE2]], i32 0, i32 1
+// CFINITEONLY-NEXT:    store half [[C_REAL]], ptr [[COERCE2_REALP]], align 2
+// CFINITEONLY-NEXT:    store half [[C_IMAG]], ptr [[COERCE2_IMAGP]], align 2
+// CFINITEONLY-NEXT:    [[TMP7:%.*]] = load <2 x half>, ptr [[COERCE2]], align 2
+// CFINITEONLY-NEXT:    [[CALL:%.*]] = call nnan ninf <2 x float> @extern_complex(<2 x float> noundef [[TMP2]], double noundef [[TMP4]], double noundef [[TMP6]], <2 x half> noundef [[TMP7]])
+// CFINITEONLY-NEXT:    store <2 x float> [[CALL]], ptr [[COERCE3]], align 4
+// CFINITEONLY-NEXT:    [[COERCE3_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE3]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[COERCE3_REAL:%.*]] = load float, ptr [[COERCE3_REALP]], align 4
+// CFINITEONLY-NEXT:    [[COERCE3_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE3]], i32 0, i32 1
+// CFINITEONLY-NEXT:    [[COERCE3_IMAG:%.*]] = load float, ptr [[COERCE3_IMAGP]], align 4
+// CFINITEONLY-NEXT:    [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1
+// CFINITEONLY-NEXT:    store float [[COERCE3_REAL]], ptr [[RETVAL_REALP]], align 4
+// CFINITEONLY-NEXT:    store float [[COERCE3_IMAG]], ptr [[RETVAL_IMAGP]], align 4
+// CFINITEONLY-NEXT:    [[TMP8:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4
+// CFINITEONLY-NEXT:    ret <2 x float> [[TMP8]]
+//
+// CLFINITEONLY: Function Attrs: convergent norecurse nounwind
+// CLFINITEONLY-LABEL: define dso_local <2 x float> @defined_complex_func
+// CLFINITEONLY-SAME: (<2 x float> noundef [[A_COERCE:%.*]], double noundef [[B_COERCE0:%.*]], double noundef [[B_COERCE1:%.*]], <2 x half> noundef [[C_COERCE:%.*]]) local_unnamed_addr #[[ATTR6:[0-9]+]] {
+// CLFINITEONLY-NEXT:  entry:
+// CLFINITEONLY-NEXT:    [[CALL:%.*]] = tail call nnan ninf <2 x float> @extern_complex(<2 x float> noundef [[A_COERCE]], double noundef [[B_COERCE0]], double noundef [[B_COERCE1]], <2 x half> noundef [[C_COERCE]]) #[[ATTR10]]
+// CLFINITEONLY-NEXT:    ret <2 x float> [[CALL]]
+//
+// NONANS: Function Attrs: noinline nounwind optnone
+// NONANS-LABEL: define dso_local <2 x float> @defined_complex_func
+// NONANS-SAME: (<2 x float> noundef [[A_COERCE:%.*]], double noundef [[B_COERCE0:%.*]], double noundef [[B_COERCE1:%.*]], <2 x half> noundef [[C_COERCE:%.*]]) #[[ATTR4:[0-9]+]] {
+// NONANS-NEXT:  entry:
+// NONANS-NEXT:    [[RETVAL:%.*]] = alloca { float, float }, align 4
+// NONANS-NEXT:    [[A:%.*]] = alloca { float, float }, align 4
+// NONANS-NEXT:    [[B:%.*]] = alloca { double, double }, align 8
+// NONANS-NEXT:    [[C:%.*]] = alloca { half, half }, align 2
+// NONANS-NEXT:    [[COERCE:%.*]] = alloca { float, float }, align 4
+// NONANS-NEXT:    [[COERCE1:%.*]] = alloca { double, double }, align 8
+// NONANS-NEXT:    [[COERCE2:%.*]] = alloca { half, half }, align 2
+// NONANS-NEXT:    [[COERCE3:%.*]] = alloca { float, float }, align 4
+// NONANS-NEXT:    store <2 x float> [[A_COERCE]], ptr [[A]], align 4
+// NONANS-NEXT:    [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0
+// NONANS-NEXT:    store double [[B_COERCE0]], ptr [[TMP0]], align 8
+// NONANS-NEXT:    [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1
+// NONANS-NEXT:    store double [[B_COERCE1]], ptr [[TMP1]], align 8
+// NONANS-NEXT:    store <2 x half> [[C_COERCE]], ptr [[C]], align 2
+// NONANS-NEXT:    [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0
+// NONANS-NEXT:    [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4
+// NONANS-NEXT:    [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1
+// NONANS-NEXT:    [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4
+// NONANS-NEXT:    [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0
+// NONANS-NEXT:    [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8
+// NONANS-NEXT:    [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1
+// NONANS-NEXT:    [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8
+// NONANS-NEXT:    [[C_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 0
+// NONANS-NEXT:    [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2
+// NONANS-NEXT:    [[C_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 1
+// NONANS-NEXT:    [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2
+// NONANS-NEXT:    [[COERCE_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 0
+// NONANS-NEXT:    [[COERCE_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 1
+// NONANS-NEXT:    store float [[A_REAL]], ptr [[COERCE_REALP]], align 4
+// NONANS-NEXT:    store float [[A_IMAG]], ptr [[COERCE_IMAGP]], align 4
+// NONANS-NEXT:    [[TMP2:%.*]] = load <2 x float>, ptr [[COERCE]], align 4
+// NONANS-NEXT:    [[COERCE1_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[COERCE1]], i32 0, i32 0
+// NONANS-NEXT:    [[COERCE1_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[COERCE1]], i32 0, i32 1
+// NONANS-NEXT:    store double [[B_REAL]], ptr [[COERCE1_REALP]], align 8
+// NONANS-NEXT:    store double [[B_IMAG]], ptr [[COERCE1_IMAGP]], align 8
+// NONANS-NEXT:    [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[COERCE1]], i32 0, i32 0
+// NONANS-NEXT:    [[TMP4:%.*]] = load double, ptr [[TMP3]], align 8
+// NONANS-NEXT:    [[TMP5:%.*]] = getelementptr inbounds { double, double }, ptr [[COERCE1]], i32 0, i32 1
+// NONANS-NEXT:    [[TMP6:%.*]] = load double, ptr [[TMP5]], align 8
+// NONANS-NEXT:    [[COERCE2_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[COERCE2]], i32 0, i32 0
+// NONANS-NEXT:    [[COERCE2_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[COERCE2]], i32 0, i32 1
+// NONANS-NEXT:    store half [[C_REAL]], ptr [[COERCE2_REALP]], align 2
+// NONANS-NEXT:    store half [[C_IMAG]], ptr [[COERCE2_IMAGP]], align 2
+// NONANS-NEXT:    [[TMP7:%.*]] = load <2 x half>, ptr [[COERCE2]], align 2
+// NONANS-NEXT:    [[CALL:%.*]] = call nnan <2 x float> @extern_complex(<2 x float> noundef [[TMP2]], double noundef [[TMP4]], double noundef [[TMP6]], <2 x half> noundef [[TMP7]])
+// NONANS-NEXT:    store <2 x float> [[CALL]], ptr [[COERCE3]], align 4
+// NONANS-NEXT:    [[COERCE3_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE3]], i32 0, i32 0
+// NONANS-NEXT:    [[COERCE3_REAL:%.*]] = load float, ptr [[COERCE3_REALP]], align 4
+// NONANS-NEXT:    [[COERCE3_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE3]], i32 0, i32 1
+// NONANS-NEXT:    [[COERCE3_IMAG:%.*]] = load float, ptr [[COERCE3_IMAGP]], align 4
+// NONANS-NEXT:    [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0
+// NONANS-NEXT:    [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1
+// NONANS-NEXT:    store float [[COERCE3_REAL]], ptr [[RETVAL_REALP]], align 4
+// NONANS-NEXT:    store float [[COERCE3_IMAG]], ptr [[RETVAL_IMAGP]], align 4
+// NONANS-NEXT:    [[TMP8:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4
+// NONANS-NEXT:    ret <2 x float> [[TMP8]]
+//
+// NOINFS: Function Attrs: noinline nounwind optnone
+// NOINFS-LABEL: define dso_local <2 x float> @defined_complex_func
+// NOINFS-SAME: (<2 x float> noundef [[A_COERCE:%.*]], double noundef [[B_COERCE0:%.*]], double noundef [[B_COERCE1:%.*]], <2 x half> noundef [[C_COERCE:%.*]]) #[[ATTR4:[0-9]+]] {
+// NOINFS-NEXT:  entry:
+// NOINFS-NEXT:    [[RETVAL:%.*]] = alloca { float, float }, align 4
+// NOINFS-NEXT:    [[A:%.*]] = alloca { float, float }, align 4
+// NOINFS-NEXT:    [[B:%.*]] = alloca { double, double }, align 8
+// NOINFS-NEXT:    [[C:%.*]] = alloca { half, half }, align 2
+// NOINFS-NEXT:    [[COERCE:%.*]] = alloca { float, float }, align 4
+// NOINFS-NEXT:    [[COERCE1:%.*]] = alloca { double, double }, align 8
+// NOINFS-NEXT:    [[COERCE2:%.*]] = alloca { half, half }, align 2
+// NOINFS-NEXT:    [[COERCE3:%.*]] = alloca { float, float }, align 4
+// NOINFS-NEXT:    store <2 x float> [[A_COERCE]], ptr [[A]], align 4
+// NOINFS-NEXT:    [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0
+// NOINFS-NEXT:    store double [[B_COERCE0]], ptr [[TMP0]], align 8
+// NOINFS-NEXT:    [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1
+// NOINFS-NEXT:    store double [[B_COERCE1]], ptr [[TMP1]], align 8
+// NOINFS-NEXT:    store <2 x half> [[C_COERCE]], ptr [[C]], align 2
+// NOINFS-NEXT:    [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0
+// NOINFS-NEXT:    [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4
+// NOINFS-NEXT:    [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1
+// NOINFS-NEXT:    [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4
+// NOINFS-NEXT:    [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0
+// NOINFS-NEXT:    [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8
+// NOINFS-NEXT:    [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1
+// NOINFS-NEXT:    [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8
+// NOINFS-NEXT:    [[C_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 0
+// NOINFS-NEXT:    [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2
+// NOINFS-NEXT:    [[C_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 1
+// NOINFS-NEXT:    [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2
+// NOINFS-NEXT:    [[COERCE_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 0
+// NOINFS-NEXT:    [[COERCE_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 1
+// NOINFS-NEXT:    store float [[A_REAL]], ptr [[COERCE_REALP]], align 4
+// NOINFS-NEXT:    store float [[A_IMAG]], ptr [[COERCE_IMAGP]], align 4
+// NOINFS-NEXT:    [[TMP2:%.*]] = load <2 x float>, ptr [[COERCE]], align 4
+// NOINFS-NEXT:    [[COERCE1_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[COERCE1]], i32 0, i32 0
+// NOINFS-NEXT:    [[COERCE1_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[COERCE1]], i32 0, i32 1
+// NOINFS-NEXT:    store double [[B_REAL]], ptr [[COERCE1_REALP]], align 8
+// NOINFS-NEXT:    store double [[B_IMAG]], ptr [[COERCE1_IMAGP]], align 8
+// NOINFS-NEXT:    [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[COERCE1]], i32 0, i32 0
+// NOINFS-NEXT:    [[TMP4:%.*]] = load double, ptr [[TMP3]], align 8
+// NOINFS-NEXT:    [[TMP5:%.*]] = getelementptr inbounds { double, double }, ptr [[COERCE1]], i32 0, i32 1
+// NOINFS-NEXT:    [[TMP6:%.*]] = load double, ptr [[TMP5]], align 8
+// NOINFS-NEXT:    [[COERCE2_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[COERCE2]], i32 0, i32 0
+// NOINFS-NEXT:    [[COERCE2_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[COERCE2]], i32 0, i32 1
+// NOINFS-NEXT:    store half [[C_REAL]], ptr [[COERCE2_REALP]], align 2
+// NOINFS-NEXT:    store half [[C_IMAG]], ptr [[COERCE2_IMAGP]], align 2
+// NOINFS-NEXT:    [[TMP7:%.*]] = load <2 x half>, ptr [[COERCE2]], align 2
+// NOINFS-NEXT:    [[CALL:%.*]] = call ninf <2 x float> @extern_complex(<2 x float> noundef [[TMP2]], double noundef [[TMP4]], double noundef [[TMP6]], <2 x half> noundef [[TMP7]])
+// NOINFS-NEXT:    store <2 x float> [[CALL]], ptr [[COERCE3]], align 4
+// NOINFS-NEXT:    [[COERCE3_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE3]], i32 0, i32 0
+// NOINFS-NEXT:    [[COERCE3_REAL:%.*]] = load float, ptr [[COERCE3_REALP]], align 4
+// NOINFS-NEXT:    [[COERCE3_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE3]], i32 0, i32 1
+// NOINFS-NEXT:    [[COERCE3_IMAG:%.*]] = load float, ptr [[COERCE3_IMAGP]], align 4
+// NOINFS-NEXT:    [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0
+// NOINFS-NEXT:    [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1
+// NOINFS-NEXT:    store float [[COERCE3_REAL]], ptr [[RETVAL_REALP]], align 4
+// NOINFS-NEXT:    store float [[COERCE3_IMAG]], ptr [[RETVAL_IMAGP]], align 4
+// NOINFS-NEXT:    [[TMP8:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4
+// NOINFS-NEXT:    ret <2 x float> [[TMP8]]
+//
+_Complex float defined_complex_func(_Complex float a, _Complex double b, _Complex _Float16 c) {
+  return extern_complex(a, b, c);
+}
+
+// CFINITEONLY: Function Attrs: noinline nounwind optnone
+// CFINITEONLY-LABEL: define dso_local { double, double } @defined_complex_func_f64_ret
+// CFINITEONLY-SAME: (double noundef [[C_COERCE0:%.*]], double noundef [[C_COERCE1:%.*]]) #[[ATTR0]] {
+// CFINITEONLY-NEXT:  entry:
+// CFINITEONLY-NEXT:    [[RETVAL:%.*]] = alloca { double, double }, align 8
+// CFINITEONLY-NEXT:    [[C:%.*]] = alloca { double, double }, align 8
+// CFINITEONLY-NEXT:    [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[C]], i32 0, i32 0
+// CFINITEONLY-NEXT:    store double [[C_COERCE0]], ptr [[TMP0]], align 8
+// CFINITEONLY-NEXT:    [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[C]], i32 0, i32 1
+// CFINITEONLY-NEXT:    store double [[C_COERCE1]], ptr [[TMP1]], align 8
+// CFINITEONLY-NEXT:    [[C_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[C]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[C_REAL:%.*]] = load double, ptr [[C_REALP]], align 8
+// CFINITEONLY-NEXT:    [[C_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[C]], i32 0, i32 1
+// CFINITEONLY-NEXT:    [[C_IMAG:%.*]] = load double, ptr [[C_IMAGP]], align 8
+// CFINITEONLY-NEXT:    [[C_REALP1:%.*]] = getelementptr inbounds { double, double }, ptr [[C]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[C_REAL2:%.*]] = load double, ptr [[C_REALP1]], align 8
+// CFINITEONLY-NEXT:    [[C_IMAGP3:%.*]] = getelementptr inbounds { double, double }, ptr [[C]], i32 0, i32 1
+// CFINITEONLY-NEXT:    [[C_IMAG4:%.*]] = load double, ptr [[C_IMAGP3]], align 8
+// CFINITEONLY-NEXT:    [[MUL_AC:%.*]] = fmul nnan ninf double [[C_REAL]], [[C_REAL2]]
+// CFINITEONLY-NEXT:    [[MUL_BD:%.*]] = fmul nnan ninf double [[C_IMAG]], [[C_IMAG4]]
+// CFINITEONLY-NEXT:    [[MUL_AD:%.*]] = fmul nnan ninf double [[C_REAL]], [[C_IMAG4]]
+// CFINITEONLY-NEXT:    [[MUL_BC:%.*]] = fmul nnan ninf double [[C_IMAG]], [[C_REAL2]]
+// CFINITEONLY-NEXT:    [[MUL_R:%.*]] = fsub nnan ninf double [[MUL_AC]], [[MUL_BD]]
+// CFINITEONLY-NEXT:    [[MUL_I:%.*]] = fadd nnan ninf double [[MUL_AD]], [[MUL_BC]]
+// CFINITEONLY-NEXT:    [[ISNAN_CMP:%.*]] = fcmp nnan ninf uno double [[MUL_R]], [[MUL_R]]
+// CFINITEONLY-NEXT:    br i1 [[ISNAN_CMP]], label [[COMPLEX_MUL_IMAG_NAN:%.*]], label [[COMPLEX_MUL_CONT:%.*]], !prof [[PROF2:![0-9]+]]
+// CFINITEONLY:       complex_mul_imag_nan:
+// CFINITEONLY-NEXT:    [[ISNAN_CMP5:%.*]] = fcmp nnan ninf uno double [[MUL_I]], [[MUL_I]]
+// CFINITEONLY-NEXT:    br i1 [[ISNAN_CMP5]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]]
+// CFINITEONLY:       complex_mul_libcall:
+// CFINITEONLY-NEXT:    [[CALL:%.*]] = call { double, double } @__muldc3(double noundef [[C_REAL]], double noundef [[C_IMAG]], double noundef [[C_REAL2]], double noundef [[C_IMAG4]]) #[[ATTR7:[0-9]+]]
+// CFINITEONLY-NEXT:    [[TMP2:%.*]] = extractvalue { double, double } [[CALL]], 0
+// CFINITEONLY-NEXT:    [[TMP3:%.*]] = extractvalue { double, double } [[CALL]], 1
+// CFINITEONLY-NEXT:    br label [[COMPLEX_MUL_CONT]]
+// CFINITEONLY:       complex_mul_cont:
+// CFINITEONLY-NEXT:    [[REAL_MUL_PHI:%.*]] = phi nnan ninf double [ [[MUL_R]], [[ENTRY:%.*]] ], [ [[MUL_R]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[TMP2]], [[COMPLEX_MUL_LIBCALL]] ]
+// CFINITEONLY-NEXT:    [[IMAG_MUL_PHI:%.*]] = phi nnan ninf double [ [[MUL_I]], [[ENTRY]] ], [ [[MUL_I]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[TMP3]], [[COMPLEX_MUL_LIBCALL]] ]
+// CFINITEONLY-NEXT:    [[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1
+// CFINITEONLY-NEXT:    store double [[REAL_MUL_PHI]], ptr [[RETVAL_REALP]], align 8
+// CFINITEONLY-NEXT:    store double [[IMAG_MUL_PHI]], ptr [[RETVAL_IMAGP]], align 8
+// CFINITEONLY-NEXT:    [[TMP4:%.*]] = load { double, double }, ptr [[RETVAL]], align 8
+// CFINITEONLY-NEXT:    ret { double, double } [[TMP4]]
+//
+// CLFINITEONLY: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
+// CLFINITEONLY-LABEL: define dso_local { double, double } @defined_complex_func_f64_ret
+// CLFINITEONLY-SAME: (double noundef [[C_COERCE0:%.*]], double noundef [[C_COERCE1:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CLFINITEONLY-NEXT:  entry:
+// CLFINITEONLY-NEXT:    [[MUL_AD:%.*]] = fmul nnan ninf double [[C_COERCE0]], [[C_COERCE1]]
+// CLFINITEONLY-NEXT:    [[MUL_I:%.*]] = fadd nnan ninf double [[MUL_AD]], [[MUL_AD]]
+// CLFINITEONLY-NEXT:    [[MUL_AC:%.*]] = fmul nnan ninf double [[C_COERCE0]], [[C_COERCE0]]
+// CLFINITEONLY-NEXT:    [[MUL_BD:%.*]] = fmul nnan ninf double [[C_COERCE1]], [[C_COERCE1]]
+// CLFINITEONLY-NEXT:    [[MUL_R:%.*]] = fsub nnan ninf double [[MUL_AC]], [[MUL_BD]]
+// CLFINITEONLY-NEXT:    [[DOTFCA_0_INSERT:%.*]] = insertvalue { double, double } poison, double [[MUL_R]], 0
+// CLFINITEONLY-NEXT:    [[DOTFCA_1_INSERT:%.*]] = insertvalue { double, double } [[DOTFCA_0_INSERT]], double [[MUL_I]], 1
+// CLFINITEONLY-NEXT:    ret { double, double } [[DOTFCA_1_INSERT]]
+//
+// NONANS: Function Attrs: noinline nounwind optnone
+// NONANS-LABEL: define dso_local { double, double } @defined_complex_func_f64_ret
+// NONANS-SAME: (double noundef [[C_COERCE0:%.*]], double noundef [[C_COERCE1:%.*]]) #[[ATTR0]] {
+// NONANS-NEXT:  entry:
+// NONANS-NEXT:    [[RETVAL:%.*]] = alloca { double, double }, align 8
+// NONANS-NEXT:    [[C:%.*]] = alloca { double, double }, align 8
+// NONANS-NEXT:    [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[C]], i32 0, i32 0
+// NONANS-NEXT:    store double [[C_COERCE0]], ptr [[TMP0]], align 8
+// NONANS-NEXT:    [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[C]], i32 0, i32 1
+// NONANS-NEXT:    store double [[C_COERCE1]], ptr [[TMP1]], align 8
+// NONANS-NEXT:    [[C_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[C]], i32 0, i32 0
+// NONANS-NEXT:    [[C_REAL:%.*]] = load double, ptr [[C_REALP]], align 8
+// NONANS-NEXT:    [[C_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[C]], i32 0, i32 1
+// NONANS-NEXT:    [[C_IMAG:%.*]] = load double, ptr [[C_IMAGP]], align 8
+// NONANS-NEXT:    [[C_REALP1:%.*]] = getelementptr inbounds { double, double }, ptr [[C]], i32 0, i32 0
+// NONANS-NEXT:    [[C_REAL2:%.*]] = load double, ptr [[C_REALP1]], align 8
+// NONANS-NEXT:    [[C_IMAGP3:%.*]] = getelementptr inbounds { double, double }, ptr [[C]], i32 0, i32 1
+// NONANS-NEXT:    [[C_IMAG4:%.*]] = load double, ptr [[C_IMAGP3]], align 8
+// NONANS-NEXT:    [[MUL_AC:%.*]] = fmul nnan double [[C_REAL]], [[C_REAL2]]
+// NONANS-NEXT:    [[MUL_BD:%.*]] = fmul nnan double [[C_IMAG]], [[C_IMAG4]]
+// NONANS-NEXT:    [[MUL_AD:%.*]] = fmul nnan double [[C_REAL]], [[C_IMAG4]]
+// NONANS-NEXT:    [[MUL_BC:%.*]] = fmul nnan double [[C_IMAG]], [[C_REAL2]]
+// NONANS-NEXT:    [[MUL_R:%.*]] = fsub nnan double [[MUL_AC]], [[MUL_BD]]
+// NONANS-NEXT:    [[MUL_I:%.*]] = fadd nnan double [[MUL_AD]], [[MUL_BC]]
+// NONANS-NEXT:    [[ISNAN_CMP:%.*]] = fcmp nnan uno double [[MUL_R]], [[MUL_R]]
+// NONANS-NEXT:    br i1 [[ISNAN_CMP]], label [[COMPLEX_MUL_IMAG_NAN:%.*]], label [[COMPLEX_MUL_CONT:%.*]], !prof [[PROF2:![0-9]+]]
+// NONANS:       complex_mul_imag_nan:
+// NONANS-NEXT:    [[ISNAN_CMP5:%.*]] = fcmp nnan uno double [[MUL_I]], [[MUL_I]]
+// NONANS-NEXT:    br i1 [[ISNAN_CMP5]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]]
+// NONANS:       complex_mul_libcall:
+// NONANS-NEXT:    [[CALL:%.*]] = call { double, double } @__muldc3(double noundef [[C_REAL]], double noundef [[C_IMAG]], double noundef [[C_REAL2]], double noundef [[C_IMAG4]]) #[[ATTR7:[0-9]+]]
+// NONANS-NEXT:    [[TMP2:%.*]] = extractvalue { double, double } [[CALL]], 0
+// NONANS-NEXT:    [[TMP3:%.*]] = extractvalue { double, double } [[CALL]], 1
+// NONANS-NEXT:    br label [[COMPLEX_MUL_CONT]]
+// NONANS:       complex_mul_cont:
+// NONANS-NEXT:    [[REAL_MUL_PHI:%.*]] = phi nnan double [ [[MUL_R]], [[ENTRY:%.*]] ], [ [[MUL_R]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[TMP2]], [[COMPLEX_MUL_LIBCALL]] ]
+// NONANS-NEXT:    [[IMAG_MUL_PHI:%.*]] = phi nnan double [ [[MUL_I]], [[ENTRY]] ], [ [[MUL_I]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[TMP3]], [[COMPLEX_MUL_LIBCALL]] ]
+// NONANS-NEXT:    [[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0
+// NONANS-NEXT:    [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1
+// NONANS-NEXT:    store double [[REAL_MUL_PHI]], ptr [[RETVAL_REALP]], align 8
+// NONANS-NEXT:    store double [[IMAG_MUL_PHI]], ptr [[RETVAL_IMAGP]], align 8
+// NONANS-NEXT:    [[TMP4:%.*]] = load { double, double }, ptr [[RETVAL]], align 8
+// NONANS-NEXT:    ret { double, double } [[TMP4]]
+//
+// NOINFS: Function Attrs: noinline nounwind optnone
+// NOINFS-LABEL: define dso_local { double, double } @defined_complex_func_f64_ret
+// NOINFS-SAME: (double noundef [[C_COERCE0:%.*]], double noundef [[C_COERCE1:%.*]]) #[[ATTR0]] {
+// NOINFS-NEXT:  entry:
+// NOINFS-NEXT:    [[RETVAL:%.*]] = alloca { double, double }, align 8
+// NOINFS-NEXT:    [[C:%.*]] = alloca { double, double }, align 8
+// NOINFS-NEXT:    [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[C]], i32 0, i32 0
+// NOINFS-NEXT:    store double [[C_COERCE0]], ptr [[TMP0]], align 8
+// NOINFS-NEXT:    [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[C]], i32 0, i32 1
+// NOINFS-NEXT:    store double [[C_COERCE1]], ptr [[TMP1]], align 8
+// NOINFS-NEXT:    [[C_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[C]], i32 0, i32 0
+// NOINFS-NEXT:    [[C_REAL:%.*]] = load double, ptr [[C_REALP]], align 8
+// NOINFS-NEXT:    [[C_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[C]], i32 0, i32 1
+// NOINFS-NEXT:    [[C_IMAG:%.*]] = load double, ptr [[C_IMAGP]], align 8
+// NOINFS-NEXT:    [[C_REALP1:%.*]] = getelementptr inbounds { double, double }, ptr [[C]], i32 0, i32 0
+// NOINFS-NEXT:    [[C_REAL2:%.*]] = load double, ptr [[C_REALP1]], align 8
+// NOINFS-NEXT:    [[C_IMAGP3:%.*]] = getelementptr inbounds { double, double }, ptr [[C]], i32 0, i32 1
+// NOINFS-NEXT:    [[C_IMAG4:%.*]] = load double, ptr [[C_IMAGP3]], align 8
+// NOINFS-NEXT:    [[MUL_AC:%.*]] = fmul ninf double [[C_REAL]], [[C_REAL2]]
+// NOINFS-NEXT:    [[MUL_BD:%.*]] = fmul ninf double [[C_IMAG]], [[C_IMAG4]]
+// NOINFS-NEXT:    [[MUL_AD:%.*]] = fmul ninf double [[C_REAL]], [[C_IMAG4]]
+// NOINFS-NEXT:    [[MUL_BC:%.*]] = fmul ninf double [[C_IMAG]], [[C_REAL2]]
+// NOINFS-NEXT:    [[MUL_R:%.*]] = fsub ninf double [[MUL_AC]], [[MUL_BD]]
+// NOINFS-NEXT:    [[MUL_I:%.*]] = fadd ninf double [[MUL_AD]], [[MUL_BC]]
+// NOINFS-NEXT:    [[ISNAN_CMP:%.*]] = fcmp ninf uno double [[MUL_R]], [[MUL_R]]
+// NOINFS-NEXT:    br i1 [[ISNAN_CMP]], label [[COMPLEX_MUL_IMAG_NAN:%.*]], label [[COMPLEX_MUL_CONT:%.*]], !prof [[PROF2:![0-9]+]]
+// NOINFS:       complex_mul_imag_nan:
+// NOINFS-NEXT:    [[ISNAN_CMP5:%.*]] = fcmp ninf uno double [[MUL_I]], [[MUL_I]]
+// NOINFS-NEXT:    br i1 [[ISNAN_CMP5]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]]
+// NOINFS:       complex_mul_libcall:
+// NOINFS-NEXT:    [[CALL:%.*]] = call { double, double } @__muldc3(double noundef [[C_REAL]], double noundef [[C_IMAG]], double noundef [[C_REAL2]], double noundef [[C_IMAG4]]) #[[ATTR7:[0-9]+]]
+// NOINFS-NEXT:    [[TMP2:%.*]] = extractvalue { double, double } [[CALL]], 0
+// NOINFS-NEXT:    [[TMP3:%.*]] = extractvalue { double, double } [[CALL]], 1
+// NOINFS-NEXT:    br label [[COMPLEX_MUL_CONT]]
+// NOINFS:       complex_mul_cont:
+// NOINFS-NEXT:    [[REAL_MUL_PHI:%.*]] = phi ninf double [ [[MUL_R]], [[ENTRY:%.*]] ], [ [[MUL_R]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[TMP2]], [[COMPLEX_MUL_LIBCALL]] ]
+// NOINFS-NEXT:    [[IMAG_MUL_PHI:%.*]] = phi ninf double [ [[MUL_I]], [[ENTRY]] ], [ [[MUL_I]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[TMP3]], [[COMPLEX_MUL_LIBCALL]] ]
+// NOINFS-NEXT:    [[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0
+// NOINFS-NEXT:    [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1
+// NOINFS-NEXT:    store double [[REAL_MUL_PHI]], ptr [[RETVAL_REALP]], align 8
+// NOINFS-NEXT:    store double [[IMAG_MUL_PHI]], ptr [[RETVAL_IMAGP]], align 8
+// NOINFS-NEXT:    [[TMP4:%.*]] = load { double, double }, ptr [[RETVAL]], align 8
+// NOINFS-NEXT:    ret { double, double } [[TMP4]]
+//
+_Complex double defined_complex_func_f64_ret(_Complex double c) {
+  return c * c;
+}
+
+// CFINITEONLY: Function Attrs: noinline nounwind optnone
+// CFINITEONLY-LABEL: define dso_local <2 x half> @defined_complex_func_f16_ret
+// CFINITEONLY-SAME: (<2 x half> noundef [[C_COERCE:%.*]]) #[[ATTR4]] {
+// CFINITEONLY-NEXT:  entry:
+// CFINITEONLY-NEXT:    [[RETVAL:%.*]] = alloca { half, half }, align 2
+// CFINITEONLY-NEXT:    [[C:%.*]] = alloca { half, half }, align 2
+// CFINITEONLY-NEXT:    [[COERCE:%.*]] = alloca { float, float }, align 4
+// CFINITEONLY-NEXT:    store <2 x half> [[C_COERCE]], ptr [[C]], align 2
+// CFINITEONLY-NEXT:    [[C_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2
+// CFINITEONLY-NEXT:    [[C_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 1
+// CFINITEONLY-NEXT:    [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2
+// CFINITEONLY-NEXT:    [[EXT:%.*]] = fpext half [[C_REAL]] to float
+// CFINITEONLY-NEXT:    [[EXT1:%.*]] = fpext half [[C_IMAG]] to float
+// CFINITEONLY-NEXT:    [[C_REALP2:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[C_REAL3:%.*]] = load half, ptr [[C_REALP2]], align 2
+// CFINITEONLY-NEXT:    [[C_IMAGP4:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 1
+// CFINITEONLY-NEXT:    [[C_IMAG5:%.*]] = load half, ptr [[C_IMAGP4]], align 2
+// CFINITEONLY-NEXT:    [[EXT6:%.*]] = fpext half [[C_REAL3]] to float
+// CFINITEONLY-NEXT:    [[EXT7:%.*]] = fpext half [[C_IMAG5]] to float
+// CFINITEONLY-NEXT:    [[MUL_AC:%.*]] = fmul nnan ninf float [[EXT]], [[EXT6]]
+// CFINITEONLY-NEXT:    [[MUL_BD:%.*]] = fmul nnan ninf float [[EXT1]], [[EXT7]]
+// CFINITEONLY-NEXT:    [[MUL_AD:%.*]] = fmul nnan ninf float [[EXT]], [[EXT7]]
+// CFINITEONLY-NEXT:    [[MUL_BC:%.*]] = fmul nnan ninf float [[EXT1]], [[EXT6]]
+// CFINITEONLY-NEXT:    [[MUL_R:%.*]] = fsub nnan ninf float [[MUL_AC]], [[MUL_BD]]
+// CFINITEONLY-NEXT:    [[MUL_I:%.*]] = fadd nnan ninf float [[MUL_AD]], [[MUL_BC]]
+// CFINITEONLY-NEXT:    [[ISNAN_CMP:%.*]] = fcmp nnan ninf uno float [[MUL_R]], [[MUL_R]]
+// CFINITEONLY-NEXT:    br i1 [[ISNAN_CMP]], label [[COMPLEX_MUL_IMAG_NAN:%.*]], label [[COMPLEX_MUL_CONT:%.*]], !prof [[PROF2]]
+// CFINITEONLY:       complex_mul_imag_nan:
+// CFINITEONLY-NEXT:    [[ISNAN_CMP8:%.*]] = fcmp nnan ninf uno float [[MUL_I]], [[MUL_I]]
+// CFINITEONLY-NEXT:    br i1 [[ISNAN_CMP8]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]]
+// CFINITEONLY:       complex_mul_libcall:
+// CFINITEONLY-NEXT:    [[CALL:%.*]] = call nnan ninf <2 x float> @__mulsc3(float noundef [[EXT]], float noundef [[EXT1]], float noundef [[EXT6]], float noundef [[EXT7]]) #[[ATTR7]]
+// CFINITEONLY-NEXT:    store <2 x float> [[CALL]], ptr [[COERCE]], align 4
+// CFINITEONLY-NEXT:    [[COERCE_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[COERCE_REAL:%.*]] = load float, ptr [[COERCE_REALP]], align 4
+// CFINITEONLY-NEXT:    [[COERCE_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 1
+// CFINITEONLY-NEXT:    [[COERCE_IMAG:%.*]] = load float, ptr [[COERCE_IMAGP]], align 4
+// CFINITEONLY-NEXT:    br label [[COMPLEX_MUL_CONT]]
+// CFINITEONLY:       complex_mul_cont:
+// CFINITEONLY-NEXT:    [[REAL_MUL_PHI:%.*]] = phi nnan ninf float [ [[MUL_R]], [[ENTRY:%.*]] ], [ [[MUL_R]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_REAL]], [[COMPLEX_MUL_LIBCALL]] ]
+// CFINITEONLY-NEXT:    [[IMAG_MUL_PHI:%.*]] = phi nnan ninf float [ [[MUL_I]], [[ENTRY]] ], [ [[MUL_I]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_IMAG]], [[COMPLEX_MUL_LIBCALL]] ]
+// CFINITEONLY-NEXT:    [[UNPROMOTION:%.*]] = fptrunc float [[REAL_MUL_PHI]] to half
+// CFINITEONLY-NEXT:    [[UNPROMOTION9:%.*]] = fptrunc float [[IMAG_MUL_PHI]] to half
+// CFINITEONLY-NEXT:    [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1
+// CFINITEONLY-NEXT:    store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2
+// CFINITEONLY-NEXT:    store half [[UNPROMOTION9]], ptr [[RETVAL_IMAGP]], align 2
+// CFINITEONLY-NEXT:    [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2
+// CFINITEONLY-NEXT:    ret <2 x half> [[TMP0]]
+//
+// CLFINITEONLY: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
+// CLFINITEONLY-LABEL: define dso_local <2 x half> @defined_complex_func_f16_ret
+// CLFINITEONLY-SAME: (<2 x half> noundef [[C_COERCE:%.*]]) local_unnamed_addr #[[ATTR7:[0-9]+]] {
+// CLFINITEONLY-NEXT:  entry:
+// CLFINITEONLY-NEXT:    [[C_SROA_0_0_VEC_EXTRACT:%.*]] = extractelement <2 x half> [[C_COERCE]], i64 0
+// CLFINITEONLY-NEXT:    [[EXT:%.*]] = fpext half [[C_SROA_0_0_VEC_EXTRACT]] to float
+// CLFINITEONLY-NEXT:    [[C_SROA_0_2_VEC_EXTRACT:%.*]] = extractelement <2 x half> [[C_COERCE]], i64 1
+// CLFINITEONLY-NEXT:    [[EXT1:%.*]] = fpext half [[C_SROA_0_2_VEC_EXTRACT]] to float
+// CLFINITEONLY-NEXT:    [[MUL_AD:%.*]] = fmul nnan ninf float [[EXT]], [[EXT1]]
+// CLFINITEONLY-NEXT:    [[MUL_I:%.*]] = fadd nnan ninf float [[MUL_AD]], [[MUL_AD]]
+// CLFINITEONLY-NEXT:    [[MUL_AC:%.*]] = fmul nnan ninf float [[EXT]], [[EXT]]
+// CLFINITEONLY-NEXT:    [[MUL_BD:%.*]] = fmul nnan ninf float [[EXT1]], [[EXT1]]
+// CLFINITEONLY-NEXT:    [[MUL_R:%.*]] = fsub nnan ninf float [[MUL_AC]], [[MUL_BD]]
+// CLFINITEONLY-NEXT:    [[UNPROMOTION:%.*]] = fptrunc float [[MUL_R]] to half
+// CLFINITEONLY-NEXT:    [[UNPROMOTION9:%.*]] = fptrunc float [[MUL_I]] to half
+// CLFINITEONLY-NEXT:    [[RETVAL_SROA_0_0_VEC_INSERT:%.*]] = insertelement <2 x half> undef, half [[UNPROMOTION]], i64 0
+// CLFINITEONLY-NEXT:    [[RETVAL_SROA_0_2_VEC_INSERT:%.*]] = insertelement <2 x half> [[RETVAL_SROA_0_0_VEC_INSERT]], half [[UNPROMOTION9]], i64 1
+// CLFINITEONLY-NEXT:    ret <2 x half> [[RETVAL_SROA_0_2_VEC_INSERT]]
+//
+// NONANS: Function Attrs: noinline nounwind optnone
+// NONANS-LABEL: define dso_local <2 x half> @defined_complex_func_f16_ret
+// NONANS-SAME: (<2 x half> noundef [[C_COERCE:%.*]]) #[[ATTR4]] {
+// NONANS-NEXT:  entry:
+// NONANS-NEXT:    [[RETVAL:%.*]] = alloca { half, half }, align 2
+// NONANS-NEXT:    [[C:%.*]] = alloca { half, half }, align 2
+// NONANS-NEXT:    [[COERCE:%.*]] = alloca { float, float }, align 4
+// NONANS-NEXT:    store <2 x half> [[C_COERCE]], ptr [[C]], align 2
+// NONANS-NEXT:    [[C_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 0
+// NONANS-NEXT:    [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2
+// NONANS-NEXT:    [[C_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 1
+// NONANS-NEXT:    [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2
+// NONANS-NEXT:    [[EXT:%.*]] = fpext half [[C_REAL]] to float
+// NONANS-NEXT:    [[EXT1:%.*]] = fpext half [[C_IMAG]] to float
+// NONANS-NEXT:    [[C_REALP2:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 0
+// NONANS-NEXT:    [[C_REAL3:%.*]] = load half, ptr [[C_REALP2]], align 2
+// NONANS-NEXT:    [[C_IMAGP4:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 1
+// NONANS-NEXT:    [[C_IMAG5:%.*]] = load half, ptr [[C_IMAGP4]], align 2
+// NONANS-NEXT:    [[EXT6:%.*]] = fpext half [[C_REAL3]] to float
+// NONANS-NEXT:    [[EXT7:%.*]] = fpext half [[C_IMAG5]] to float
+// NONANS-NEXT:    [[MUL_AC:%.*]] = fmul nnan float [[EXT]], [[EXT6]]
+// NONANS-NEXT:    [[MUL_BD:%.*]] = fmul nnan float [[EXT1]], [[EXT7]]
+// NONANS-NEXT:    [[MUL_AD:%.*]] = fmul nnan float [[EXT]], [[EXT7]]
+// NONANS-NEXT:    [[MUL_BC:%.*]] = fmul nnan float [[EXT1]], [[EXT6]]
+// NONANS-NEXT:    [[MUL_R:%.*]] = fsub nnan float [[MUL_AC]], [[MUL_BD]]
+// NONANS-NEXT:    [[MUL_I:%.*]] = fadd nnan float [[MUL_AD]], [[MUL_BC]]
+// NONANS-NEXT:    [[ISNAN_CMP:%.*]] = fcmp nnan uno float [[MUL_R]], [[MUL_R]]
+// NONANS-NEXT:    br i1 [[ISNAN_CMP]], label [[COMPLEX_MUL_IMAG_NAN:%.*]], label [[COMPLEX_MUL_CONT:%.*]], !prof [[PROF2]]
+// NONANS:       complex_mul_imag_nan:
+// NONANS-NEXT:    [[ISNAN_CMP8:%.*]] = fcmp nnan uno float [[MUL_I]], [[MUL_I]]
+// NONANS-NEXT:    br i1 [[ISNAN_CMP8]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]]
+// NONANS:       complex_mul_libcall:
+// NONANS-NEXT:    [[CALL:%.*]] = call nnan <2 x float> @__mulsc3(float noundef [[EXT]], float noundef [[EXT1]], float noundef [[EXT6]], float noundef [[EXT7]]) #[[ATTR7]]
+// NONANS-NEXT:    store <2 x float> [[CALL]], ptr [[COERCE]], align 4
+// NONANS-NEXT:    [[COERCE_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 0
+// NONANS-NEXT:    [[COERCE_REAL:%.*]] = load float, ptr [[COERCE_REALP]], align 4
+// NONANS-NEXT:    [[COERCE_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 1
+// NONANS-NEXT:    [[COERCE_IMAG:%.*]] = load float, ptr [[COERCE_IMAGP]], align 4
+// NONANS-NEXT:    br label [[COMPLEX_MUL_CONT]]
+// NONANS:       complex_mul_cont:
+// NONANS-NEXT:    [[REAL_MUL_PHI:%.*]] = phi nnan float [ [[MUL_R]], [[ENTRY:%.*]] ], [ [[MUL_R]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_REAL]], [[COMPLEX_MUL_LIBCALL]] ]
+// NONANS-NEXT:    [[IMAG_MUL_PHI:%.*]] = phi nnan float [ [[MUL_I]], [[ENTRY]] ], [ [[MUL_I]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_IMAG]], [[COMPLEX_MUL_LIBCALL]] ]
+// NONANS-NEXT:    [[UNPROMOTION:%.*]] = fptrunc float [[REAL_MUL_PHI]] to half
+// NONANS-NEXT:    [[UNPROMOTION9:%.*]] = fptrunc float [[IMAG_MUL_PHI]] to half
+// NONANS-NEXT:    [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0
+// NONANS-NEXT:    [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1
+// NONANS-NEXT:    store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2
+// NONANS-NEXT:    store half [[UNPROMOTION9]], ptr [[RETVAL_IMAGP]], align 2
+// NONANS-NEXT:    [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2
+// NONANS-NEXT:    ret <2 x half> [[TMP0]]
+//
+// NOINFS: Function Attrs: noinline nounwind optnone
+// NOINFS-LABEL: define dso_local <2 x half> @defined_complex_func_f16_ret
+// NOINFS-SAME: (<2 x half> noundef [[C_COERCE:%.*]]) #[[ATTR4]] {
+// NOINFS-NEXT:  entry:
+// NOINFS-NEXT:    [[RETVAL:%.*]] = alloca { half, half }, align 2
+// NOINFS-NEXT:    [[C:%.*]] = alloca { half, half }, align 2
+// NOINFS-NEXT:    [[COERCE:%.*]] = alloca { float, float }, align 4
+// NOINFS-NEXT:    store <2 x half> [[C_COERCE]], ptr [[C]], align 2
+// NOINFS-NEXT:    [[C_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 0
+// NOINFS-NEXT:    [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2
+// NOINFS-NEXT:    [[C_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 1
+// NOINFS-NEXT:    [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2
+// NOINFS-NEXT:    [[EXT:%.*]] = fpext half [[C_REAL]] to float
+// NOINFS-NEXT:    [[EXT1:%.*]] = fpext half [[C_IMAG]] to float
+// NOINFS-NEXT:    [[C_REALP2:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 0
+// NOINFS-NEXT:    [[C_REAL3:%.*]] = load half, ptr [[C_REALP2]], align 2
+// NOINFS-NEXT:    [[C_IMAGP4:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 1
+// NOINFS-NEXT:    [[C_IMAG5:%.*]] = load half, ptr [[C_IMAGP4]], align 2
+// NOINFS-NEXT:    [[EXT6:%.*]] = fpext half [[C_REAL3]] to float
+// NOINFS-NEXT:    [[EXT7:%.*]] = fpext half [[C_IMAG5]] to float
+// NOINFS-NEXT:    [[MUL_AC:%.*]] = fmul ninf float [[EXT]], [[EXT6]]
+// NOINFS-NEXT:    [[MUL_BD:%.*]] = fmul ninf float [[EXT1]], [[EXT7]]
+// NOINFS-NEXT:    [[MUL_AD:%.*]] = fmul ninf float [[EXT]], [[EXT7]]
+// NOINFS-NEXT:    [[MUL_BC:%.*]] = fmul ninf float [[EXT1]], [[EXT6]]
+// NOINFS-NEXT:    [[MUL_R:%.*]] = fsub ninf float [[MUL_AC]], [[MUL_BD]]
+// NOINFS-NEXT:    [[MUL_I:%.*]] = fadd ninf float [[MUL_AD]], [[MUL_BC]]
+// NOINFS-NEXT:    [[ISNAN_CMP:%.*]] = fcmp ninf uno float [[MUL_R]], [[MUL_R]]
+// NOINFS-NEXT:    br i1 [[ISNAN_CMP]], label [[COMPLEX_MUL_IMAG_NAN:%.*]], label [[COMPLEX_MUL_CONT:%.*]], !prof [[PROF2]]
+// NOINFS:       complex_mul_imag_nan:
+// NOINFS-NEXT:    [[ISNAN_CMP8:%.*]] = fcmp ninf uno float [[MUL_I]], [[MUL_I]]
+// NOINFS-NEXT:    br i1 [[ISNAN_CMP8]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]]
+// NOINFS:       complex_mul_libcall:
+// NOINFS-NEXT:    [[CALL:%.*]] = call ninf <2 x float> @__mulsc3(float noundef [[EXT]], float noundef [[EXT1]], float noundef [[EXT6]], float noundef [[EXT7]]) #[[ATTR7]]
+// NOINFS-NEXT:    store <2 x float> [[CALL]], ptr [[COERCE]], align 4
+// NOINFS-NEXT:    [[COERCE_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 0
+// NOINFS-NEXT:    [[COERCE_REAL:%.*]] = load float, ptr [[COERCE_REALP]], align 4
+// NOINFS-NEXT:    [[COERCE_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 1
+// NOINFS-NEXT:    [[COERCE_IMAG:%.*]] = load float, ptr [[COERCE_IMAGP]], align 4
+// NOINFS-NEXT:    br label [[COMPLEX_MUL_CONT]]
+// NOINFS:       complex_mul_cont:
+// NOINFS-NEXT:    [[REAL_MUL_PHI:%.*]] = phi ninf float [ [[MUL_R]], [[ENTRY:%.*]] ], [ [[MUL_R]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_REAL]], [[COMPLEX_MUL_LIBCALL]] ]
+// NOINFS-NEXT:    [[IMAG_MUL_PHI:%.*]] = phi ninf float [ [[MUL_I]], [[ENTRY]] ], [ [[MUL_I]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_IMAG]], [[COMPLEX_MUL_LIBCALL]] ]
+// NOINFS-NEXT:    [[UNPROMOTION:%.*]] = fptrunc float [[REAL_MUL_PHI]] to half
+// NOINFS-NEXT:    [[UNPROMOTION9:%.*]] = fptrunc float [[IMAG_MUL_PHI]] to half
+// NOINFS-NEXT:    [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0
+// NOINFS-NEXT:    [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1
+// NOINFS-NEXT:    store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2
+// NOINFS-NEXT:    store half [[UNPROMOTION9]], ptr [[RETVAL_IMAGP]], align 2
+// NOINFS-NEXT:    [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2
+// NOINFS-NEXT:    ret <2 x half> [[TMP0]]
+//
+_Complex _Float16 defined_complex_func_f16_ret(_Complex _Float16 c) {
+  return c * c;
+}
+
+// CFINITEONLY: Function Attrs: noinline nounwind optnone
+// CFINITEONLY-LABEL: define dso_local float @call_variadic
+// CFINITEONLY-SAME: (float noundef [[F32:%.*]], double noundef [[F64:%.*]], half noundef [[F16:%.*]], double noundef [[V2F32_COERCE:%.*]], <2 x double> noundef [[V2F64:%.*]], i32 noundef [[V2F16_COERCE:%.*]], <2 x float> noundef [[CF32_COERCE:%.*]], double noundef [[CF64_COERCE0:%.*]], double noundef [[CF64_COERCE1:%.*]], ptr noundef byval({ half, half }) align 8 [[CF16:%.*]]) #[[ATTR2]] {
+// CFINITEONLY-NEXT:  entry:
+// CFINITEONLY-NEXT:    [[V2F32:%.*]] = alloca <2 x float>, align 8
+// CFINITEONLY-NEXT:    [[V2F16:%.*]] = alloca <2 x half>, align 4
+// CFINITEONLY-NEXT:    [[CF32:%.*]] = alloca { float, float }, align 4
+// CFINITEONLY-NEXT:    [[CF64:%.*]] = alloca { double, double }, align 8
+// CFINITEONLY-NEXT:    [[F32_ADDR:%.*]] = alloca float, align 4
+// CFINITEONLY-NEXT:    [[F64_ADDR:%.*]] = alloca double, align 8
+// CFINITEONLY-NEXT:    [[F16_ADDR:%.*]] = alloca half, align 2
+// CFINITEONLY-NEXT:    [[V2F32_ADDR:%.*]] = alloca <2 x float>, align 8
+// CFINITEONLY-NEXT:    [[V2F64_ADDR:%.*]] = alloca <2 x double>, align 16
+// CFINITEONLY-NEXT:    [[V2F16_ADDR:%.*]] = alloca <2 x half>, align 4
+// CFINITEONLY-NEXT:    [[COERCE:%.*]] = alloca <2 x float>, align 8
+// CFINITEONLY-NEXT:    [[COERCE3:%.*]] = alloca <2 x half>, align 4
+// CFINITEONLY-NEXT:    [[COERCE4:%.*]] = alloca { float, float }, align 4
+// CFINITEONLY-NEXT:    [[INDIRECT_ARG_TEMP:%.*]] = alloca { double, double }, align 8
+// CFINITEONLY-NEXT:    [[COERCE5:%.*]] = alloca { half, half }, align 2
+// CFINITEONLY-NEXT:    store double [[V2F32_COERCE]], ptr [[V2F32]], align 8
+// CFINITEONLY-NEXT:    [[V2F321:%.*]] = load <2 x float>, ptr [[V2F32]], align 8
+// CFINITEONLY-NEXT:    store i32 [[V2F16_COERCE]], ptr [[V2F16]], align 4
+// CFINITEONLY-NEXT:    [[V2F162:%.*]] = load <2 x half>, ptr [[V2F16]], align 4
+// CFINITEONLY-NEXT:    store <2 x float> [[CF32_COERCE]], ptr [[CF32]], align 4
+// CFINITEONLY-NEXT:    [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 0
+// CFINITEONLY-NEXT:    store double [[CF64_COERCE0]], ptr [[TMP0]], align 8
+// CFINITEONLY-NEXT:    [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 1
+// CFINITEONLY-NEXT:    store double [[CF64_COERCE1]], ptr [[TMP1]], align 8
+// CFINITEONLY-NEXT:    store float [[F32]], ptr [[F32_ADDR]], align 4
+// CFINITEONLY-NEXT:    store double [[F64]], ptr [[F64_ADDR]], align 8
+// CFINITEONLY-NEXT:    store half [[F16]], ptr [[F16_ADDR]], align 2
+// CFINITEONLY-NEXT:    store <2 x float> [[V2F321]], ptr [[V2F32_ADDR]], align 8
+// CFINITEONLY-NEXT:    store <2 x double> [[V2F64]], ptr [[V2F64_ADDR]], align 16
+// CFINITEONLY-NEXT:    store <2 x half> [[V2F162]], ptr [[V2F16_ADDR]], align 4
+// CFINITEONLY-NEXT:    [[TMP2:%.*]] = load float, ptr [[F32_ADDR]], align 4
+// CFINITEONLY-NEXT:    [[TMP3:%.*]] = load float, ptr [[F32_ADDR]], align 4
+// CFINITEONLY-NEXT:    [[CONV:%.*]] = fpext float [[TMP3]] to double
+// CFINITEONLY-NEXT:    [[TMP4:%.*]] = load double, ptr [[F64_ADDR]], align 8
+// CFINITEONLY-NEXT:    [[TMP5:%.*]] = load half, ptr [[F16_ADDR]], align 2
+// CFINITEONLY-NEXT:    [[TMP6:%.*]] = load <2 x float>, ptr [[V2F32_ADDR]], align 8
+// CFINITEONLY-NEXT:    [[TMP7:%.*]] = load <2 x double>, ptr [[V2F64_ADDR]], align 16
+// CFINITEONLY-NEXT:    [[TMP8:%.*]] = load <2 x half>, ptr [[V2F16_ADDR]], align 4
+// CFINITEONLY-NEXT:    [[CF32_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[CF32]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[CF32_REAL:%.*]] = load float, ptr [[CF32_REALP]], align 4
+// CFINITEONLY-NEXT:    [[CF32_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[CF32]], i32 0, i32 1
+// CFINITEONLY-NEXT:    [[CF32_IMAG:%.*]] = load float, ptr [[CF32_IMAGP]], align 4
+// CFINITEONLY-NEXT:    [[CF64_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[CF64_REAL:%.*]] = load double, ptr [[CF64_REALP]], align 8
+// CFINITEONLY-NEXT:    [[CF64_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 1
+// CFINITEONLY-NEXT:    [[CF64_IMAG:%.*]] = load double, ptr [[CF64_IMAGP]], align 8
+// CFINITEONLY-NEXT:    [[CF16_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[CF16]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[CF16_REAL:%.*]] = load half, ptr [[CF16_REALP]], align 8
+// CFINITEONLY-NEXT:    [[CF16_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[CF16]], i32 0, i32 1
+// CFINITEONLY-NEXT:    [[CF16_IMAG:%.*]] = load half, ptr [[CF16_IMAGP]], align 2
+// CFINITEONLY-NEXT:    store <2 x float> [[TMP6]], ptr [[COERCE]], align 8
+// CFINITEONLY-NEXT:    [[TMP9:%.*]] = load double, ptr [[COERCE]], align 8
+// CFINITEONLY-NEXT:    store <2 x half> [[TMP8]], ptr [[COERCE3]], align 4
+// CFINITEONLY-NEXT:    [[TMP10:%.*]] = load i32, ptr [[COERCE3]], align 4
+// CFINITEONLY-NEXT:    [[COERCE4_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE4]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[COERCE4_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE4]], i32 0, i32 1
+// CFINITEONLY-NEXT:    store float [[CF32_REAL]], ptr [[COERCE4_REALP]], align 4
+// CFINITEONLY-NEXT:    store float [[CF32_IMAG]], ptr [[COERCE4_IMAGP]], align 4
+// CFINITEONLY-NEXT:    [[TMP11:%.*]] = load <2 x float>, ptr [[COERCE4]], align 4
+// CFINITEONLY-NEXT:    [[INDIRECT_ARG_TEMP_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[INDIRECT_ARG_TEMP]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[INDIRECT_ARG_TEMP_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[INDIRECT_ARG_TEMP]], i32 0, i32 1
+// CFINITEONLY-NEXT:    store double [[CF64_REAL]], ptr [[INDIRECT_ARG_TEMP_REALP]], align 8
+// CFINITEONLY-NEXT:    store double [[CF64_IMAG]], ptr [[INDIRECT_ARG_TEMP_IMAGP]], align 8
+// CFINITEONLY-NEXT:    [[COERCE5_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[COERCE5]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[COERCE5_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[COERCE5]], i32 0, i32 1
+// CFINITEONLY-NEXT:    store half [[CF16_REAL]], ptr [[COERCE5_REALP]], align 2
+// CFINITEONLY-NEXT:    store half [[CF16_IMAG]], ptr [[COERCE5_IMAGP]], align 2
+// CFINITEONLY-NEXT:    [[TMP12:%.*]] = load <2 x half>, ptr [[COERCE5]], align 2
+// CFINITEONLY-NEXT:    [[CALL:%.*]] = call nnan ninf float (float, ...) @variadic(float noundef [[TMP2]], double noundef [[CONV]], double noundef [[TMP4]], half noundef [[TMP5]], double noundef [[TMP9]], <2 x double> noundef [[TMP7]], i32 noundef [[TMP10]], <2 x float> noundef [[TMP11]], ptr noundef byval({ double, double }) align 8 [[INDIRECT_ARG_TEMP]], <2 x half> noundef [[TMP12]])
+// CFINITEONLY-NEXT:    ret float [[CALL]]
+//
+// CLFINITEONLY: Function Attrs: convergent norecurse nounwind
+// CLFINITEONLY-LABEL: define dso_local float @call_variadic
+// CLFINITEONLY-SAME: (float noundef [[F32:%.*]], double noundef [[F64:%.*]], half noundef [[F16:%.*]], double noundef [[V2F32_COERCE:%.*]], <2 x double> noundef [[V2F64:%.*]], i32 noundef [[V2F16_COERCE:%.*]], <2 x float> noundef [[CF32_COERCE:%.*]], double noundef [[CF64_COERCE0:%.*]], double noundef [[CF64_COERCE1:%.*]], ptr nocapture noundef readonly byval({ half, half }) align 8 [[CF16:%.*]]) local_unnamed_addr #[[ATTR5]] {
+// CLFINITEONLY-NEXT:  entry:
+// CLFINITEONLY-NEXT:    [[INDIRECT_ARG_TEMP:%.*]] = alloca { double, double }, align 8
+// CLFINITEONLY-NEXT:    [[CONV:%.*]] = fpext float [[F32]] to double
+// CLFINITEONLY-NEXT:    [[CF16_REAL:%.*]] = load half, ptr [[CF16]], align 8
+// CLFINITEONLY-NEXT:    [[CF16_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[CF16]], i64 0, i32 1
+// CLFINITEONLY-NEXT:    [[CF16_IMAG:%.*]] = load half, ptr [[CF16_IMAGP]], align 2
+// CLFINITEONLY-NEXT:    [[INDIRECT_ARG_TEMP_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[INDIRECT_ARG_TEMP]], i64 0, i32 1
+// CLFINITEONLY-NEXT:    store double [[CF64_COERCE0]], ptr [[INDIRECT_ARG_TEMP]], align 8
+// CLFINITEONLY-NEXT:    store double [[CF64_COERCE1]], ptr [[INDIRECT_ARG_TEMP_IMAGP]], align 8
+// CLFINITEONLY-NEXT:    [[COERCE5_SROA_0_0_VEC_INSERT:%.*]] = insertelement <2 x half> undef, half [[CF16_REAL]], i64 0
+// CLFINITEONLY-NEXT:    [[COERCE5_SROA_0_2_VEC_INSERT:%.*]] = insertelement <2 x half> [[COERCE5_SROA_0_0_VEC_INSERT]], half [[CF16_IMAG]], i64 1
+// CLFINITEONLY-NEXT:    [[CALL:%.*]] = tail call nnan ninf float (float, ...) @variadic(float noundef [[F32]], double noundef [[CONV]], double noundef [[F64]], half noundef [[F16]], double noundef [[V2F32_COERCE]], <2 x double> noundef [[V2F64]], i32 noundef [[V2F16_COERCE]], <2 x float> noundef [[CF32_COERCE]], ptr noundef nonnull byval({ double, double }) align 8 [[INDIRECT_ARG_TEMP]], <2 x half> noundef [[COERCE5_SROA_0_2_VEC_INSERT]]) #[[ATTR10]]
+// CLFINITEONLY-NEXT:    ret float [[CALL]]
+//
+// NONANS: Function Attrs: noinline nounwind optnone
+// NONANS-LABEL: define dso_local float @call_variadic
+// NONANS-SAME: (float noundef [[F32:%.*]], double noundef [[F64:%.*]], half noundef [[F16:%.*]], double noundef [[V2F32_COERCE:%.*]], <2 x double> noundef [[V2F64:%.*]], i32 noundef [[V2F16_COERCE:%.*]], <2 x float> noundef [[CF32_COERCE:%.*]], double noundef [[CF64_COERCE0:%.*]], double noundef [[CF64_COERCE1:%.*]], ptr noundef byval({ half, half }) align 8 [[CF16:%.*]]) #[[ATTR2]] {
+// NONANS-NEXT:  entry:
+// NONANS-NEXT:    [[V2F32:%.*]] = alloca <2 x float>, align 8
+// NONANS-NEXT:    [[V2F16:%.*]] = alloca <2 x half>, align 4
+// NONANS-NEXT:    [[CF32:%.*]] = alloca { float, float }, align 4
+// NONANS-NEXT:    [[CF64:%.*]] = alloca { double, double }, align 8
+// NONANS-NEXT:    [[F32_ADDR:%.*]] = alloca float, align 4
+// NONANS-NEXT:    [[F64_ADDR:%.*]] = alloca double, align 8
+// NONANS-NEXT:    [[F16_ADDR:%.*]] = alloca half, align 2
+// NONANS-NEXT:    [[V2F32_ADDR:%.*]] = alloca <2 x float>, align 8
+// NONANS-NEXT:    [[V2F64_ADDR:%.*]] = alloca <2 x double>, align 16
+// NONANS-NEXT:    [[V2F16_ADDR:%.*]] = alloca <2 x half>, align 4
+// NONANS-NEXT:    [[COERCE:%.*]] = alloca <2 x float>, align 8
+// NONANS-NEXT:    [[COERCE3:%.*]] = alloca <2 x half>, align 4
+// NONANS-NEXT:    [[COERCE4:%.*]] = alloca { float, float }, align 4
+// NONANS-NEXT:    [[INDIRECT_ARG_TEMP:%.*]] = alloca { double, double }, align 8
+// NONANS-NEXT:    [[COERCE5:%.*]] = alloca { half, half }, align 2
+// NONANS-NEXT:    store double [[V2F32_COERCE]], ptr [[V2F32]], align 8
+// NONANS-NEXT:    [[V2F321:%.*]] = load <2 x float>, ptr [[V2F32]], align 8
+// NONANS-NEXT:    store i32 [[V2F16_COERCE]], ptr [[V2F16]], align 4
+// NONANS-NEXT:    [[V2F162:%.*]] = load <2 x half>, ptr [[V2F16]], align 4
+// NONANS-NEXT:    store <2 x float> [[CF32_COERCE]], ptr [[CF32]], align 4
+// NONANS-NEXT:    [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 0
+// NONANS-NEXT:    store double [[CF64_COERCE0]], ptr [[TMP0]], align 8
+// NONANS-NEXT:    [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 1
+// NONANS-NEXT:    store double [[CF64_COERCE1]], ptr [[TMP1]], align 8
+// NONANS-NEXT:    store float [[F32]], ptr [[F32_ADDR]], align 4
+// NONANS-NEXT:    store double [[F64]], ptr [[F64_ADDR]], align 8
+// NONANS-NEXT:    store half [[F16]], ptr [[F16_ADDR]], align 2
+// NONANS-NEXT:    store <2 x float> [[V2F321]], ptr [[V2F32_ADDR]], align 8
+// NONANS-NEXT:    store <2 x double> [[V2F64]], ptr [[V2F64_ADDR]], align 16
+// NONANS-NEXT:    store <2 x half> [[V2F162]], ptr [[V2F16_ADDR]], align 4
+// NONANS-NEXT:    [[TMP2:%.*]] = load float, ptr [[F32_ADDR]], align 4
+// NONANS-NEXT:    [[TMP3:%.*]] = load float, ptr [[F32_ADDR]], align 4
+// NONANS-NEXT:    [[CONV:%.*]] = fpext float [[TMP3]] to double
+// NONANS-NEXT:    [[TMP4:%.*]] = load double, ptr [[F64_ADDR]], align 8
+// NONANS-NEXT:    [[TMP5:%.*]] = load half, ptr [[F16_ADDR]], align 2
+// NONANS-NEXT:    [[TMP6:%.*]] = load <2 x float>, ptr [[V2F32_ADDR]], align 8
+// NONANS-NEXT:    [[TMP7:%.*]] = load <2 x double>, ptr [[V2F64_ADDR]], align 16
+// NONANS-NEXT:    [[TMP8:%.*]] = load <2 x half>, ptr [[V2F16_ADDR]], align 4
+// NONANS-NEXT:    [[CF32_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[CF32]], i32 0, i32 0
+// NONANS-NEXT:    [[CF32_REAL:%.*]] = load float, ptr [[CF32_REALP]], align 4
+// NONANS-NEXT:    [[CF32_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[CF32]], i32 0, i32 1
+// NONANS-NEXT:    [[CF32_IMAG:%.*]] = load float, ptr [[CF32_IMAGP]], align 4
+// NONANS-NEXT:    [[CF64_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 0
+// NONANS-NEXT:    [[CF64_REAL:%.*]] = load double, ptr [[CF64_REALP]], align 8
+// NONANS-NEXT:    [[CF64_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 1
+// NONANS-NEXT:    [[CF64_IMAG:%.*]] = load double, ptr [[CF64_IMAGP]], align 8
+// NONANS-NEXT:    [[CF16_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[CF16]], i32 0, i32 0
+// NONANS-NEXT:    [[CF16_REAL:%.*]] = load half, ptr [[CF16_REALP]], align 8
+// NONANS-NEXT:    [[CF16_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[CF16]], i32 0, i32 1
+// NONANS-NEXT:    [[CF16_IMAG:%.*]] = load half, ptr [[CF16_IMAGP]], align 2
+// NONANS-NEXT:    store <2 x float> [[TMP6]], ptr [[COERCE]], align 8
+// NONANS-NEXT:    [[TMP9:%.*]] = load double, ptr [[COERCE]], align 8
+// NONANS-NEXT:    store <2 x half> [[TMP8]], ptr [[COERCE3]], align 4
+// NONANS-NEXT:    [[TMP10:%.*]] = load i32, ptr [[COERCE3]], align 4
+// NONANS-NEXT:    [[COERCE4_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE4]], i32 0, i32 0
+// NONANS-NEXT:    [[COERCE4_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE4]], i32 0, i32 1
+// NONANS-NEXT:    store float [[CF32_REAL]], ptr [[COERCE4_REALP]], align 4
+// NONANS-NEXT:    store float [[CF32_IMAG]], ptr [[COERCE4_IMAGP]], align 4
+// NONANS-NEXT:    [[TMP11:%.*]] = load <2 x float>, ptr [[COERCE4]], align 4
+// NONANS-NEXT:    [[INDIRECT_ARG_TEMP_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[INDIRECT_ARG_TEMP]], i32 0, i32 0
+// NONANS-NEXT:    [[INDIRECT_ARG_TEMP_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[INDIRECT_ARG_TEMP]], i32 0, i32 1
+// NONANS-NEXT:    store double [[CF64_REAL]], ptr [[INDIRECT_ARG_TEMP_REALP]], align 8
+// NONANS-NEXT:    store double [[CF64_IMAG]], ptr [[INDIRECT_ARG_TEMP_IMAGP]], align 8
+// NONANS-NEXT:    [[COERCE5_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[COERCE5]], i32 0, i32 0
+// NONANS-NEXT:    [[COERCE5_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[COERCE5]], i32 0, i32 1
+// NONANS-NEXT:    store half [[CF16_REAL]], ptr [[COERCE5_REALP]], align 2
+// NONANS-NEXT:    store half [[CF16_IMAG]], ptr [[COERCE5_IMAGP]], align 2
+// NONANS-NEXT:    [[TMP12:%.*]] = load <2 x half>, ptr [[COERCE5]], align 2
+// NONANS-NEXT:    [[CALL:%.*]] = call nnan float (float, ...) @variadic(float noundef [[TMP2]], double noundef [[CONV]], double noundef [[TMP4]], half noundef [[TMP5]], double noundef [[TMP9]], <2 x double> noundef [[TMP7]], i32 noundef [[TMP10]], <2 x float> noundef [[TMP11]], ptr noundef byval({ double, double }) align 8 [[INDIRECT_ARG_TEMP]], <2 x half> noundef [[TMP12]])
+// NONANS-NEXT:    ret float [[CALL]]
+//
+// NOINFS: Function Attrs: noinline nounwind optnone
+// NOINFS-LABEL: define dso_local float @call_variadic
+// NOINFS-SAME: (float noundef [[F32:%.*]], double noundef [[F64:%.*]], half noundef [[F16:%.*]], double noundef [[V2F32_COERCE:%.*]], <2 x double> noundef [[V2F64:%.*]], i32 noundef [[V2F16_COERCE:%.*]], <2 x float> noundef [[CF32_COERCE:%.*]], double noundef [[CF64_COERCE0:%.*]], double noundef [[CF64_COERCE1:%.*]], ptr noundef byval({ half, half }) align 8 [[CF16:%.*]]) #[[ATTR2]] {
+// NOINFS-NEXT:  entry:
+// NOINFS-NEXT:    [[V2F32:%.*]] = alloca <2 x float>, align 8
+// NOINFS-NEXT:    [[V2F16:%.*]] = alloca <2 x half>, align 4
+// NOINFS-NEXT:    [[CF32:%.*]] = alloca { float, float }, align 4
+// NOINFS-NEXT:    [[CF64:%.*]] = alloca { double, double }, align 8
+// NOINFS-NEXT:    [[F32_ADDR:%.*]] = alloca float, align 4
+// NOINFS-NEXT:    [[F64_ADDR:%.*]] = alloca double, align 8
+// NOINFS-NEXT:    [[F16_ADDR:%.*]] = alloca half, align 2
+// NOINFS-NEXT:    [[V2F32_ADDR:%.*]] = alloca <2 x float>, align 8
+// NOINFS-NEXT:    [[V2F64_ADDR:%.*]] = alloca <2 x double>, align 16
+// NOINFS-NEXT:    [[V2F16_ADDR:%.*]] = alloca <2 x half>, align 4
+// NOINFS-NEXT:    [[COERCE:%.*]] = alloca <2 x float>, align 8
+// NOINFS-NEXT:    [[COERCE3:%.*]] = alloca <2 x half>, align 4
+// NOINFS-NEXT:    [[COERCE4:%.*]] = alloca { float, float }, align 4
+// NOINFS-NEXT:    [[INDIRECT_ARG_TEMP:%.*]] = alloca { double, double }, align 8
+// NOINFS-NEXT:    [[COERCE5:%.*]] = alloca { half, half }, align 2
+// NOINFS-NEXT:    store double [[V2F32_COERCE]], ptr [[V2F32]], align 8
+// NOINFS-NEXT:    [[V2F321:%.*]] = load <2 x float>, ptr [[V2F32]], align 8
+// NOINFS-NEXT:    store i32 [[V2F16_COERCE]], ptr [[V2F16]], align 4
+// NOINFS-NEXT:    [[V2F162:%.*]] = load <2 x half>, ptr [[V2F16]], align 4
+// NOINFS-NEXT:    store <2 x float> [[CF32_COERCE]], ptr [[CF32]], align 4
+// NOINFS-NEXT:    [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 0
+// NOINFS-NEXT:    store double [[CF64_COERCE0]], ptr [[TMP0]], align 8
+// NOINFS-NEXT:    [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 1
+// NOINFS-NEXT:    store double [[CF64_COERCE1]], ptr [[TMP1]], align 8
+// NOINFS-NEXT:    store float [[F32]], ptr [[F32_ADDR]], align 4
+// NOINFS-NEXT:    store double [[F64]], ptr [[F64_ADDR]], align 8
+// NOINFS-NEXT:    store half [[F16]], ptr [[F16_ADDR]], align 2
+// NOINFS-NEXT:    store <2 x float> [[V2F321]], ptr [[V2F32_ADDR]], align 8
+// NOINFS-NEXT:    store <2 x double> [[V2F64]], ptr [[V2F64_ADDR]], align 16
+// NOINFS-NEXT:    store <2 x half> [[V2F162]], ptr [[V2F16_ADDR]], align 4
+// NOINFS-NEXT:    [[TMP2:%.*]] = load float, ptr [[F32_ADDR]], align 4
+// NOINFS-NEXT:    [[TMP3:%.*]] = load float, ptr [[F32_ADDR]], align 4
+// NOINFS-NEXT:    [[CONV:%.*]] = fpext float [[TMP3]] to double
+// NOINFS-NEXT:    [[TMP4:%.*]] = load double, ptr [[F64_ADDR]], align 8
+// NOINFS-NEXT:    [[TMP5:%.*]] = load half, ptr [[F16_ADDR]], align 2
+// NOINFS-NEXT:    [[TMP6:%.*]] = load <2 x float>, ptr [[V2F32_ADDR]], align 8
+// NOINFS-NEXT:    [[TMP7:%.*]] = load <2 x double>, ptr [[V2F64_ADDR]], align 16
+// NOINFS-NEXT:    [[TMP8:%.*]] = load <2 x half>, ptr [[V2F16_ADDR]], align 4
+// NOINFS-NEXT:    [[CF32_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[CF32]], i32 0, i32 0
+// NOINFS-NEXT:    [[CF32_REAL:%.*]] = load float, ptr [[CF32_REALP]], align 4
+// NOINFS-NEXT:    [[CF32_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[CF32]], i32 0, i32 1
+// NOINFS-NEXT:    [[CF32_IMAG:%.*]] = load float, ptr [[CF32_IMAGP]], align 4
+// NOINFS-NEXT:    [[CF64_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 0
+// NOINFS-NEXT:    [[CF64_REAL:%.*]] = load double, ptr [[CF64_REALP]], align 8
+// NOINFS-NEXT:    [[CF64_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 1
+// NOINFS-NEXT:    [[CF64_IMAG:%.*]] = load double, ptr [[CF64_IMAGP]], align 8
+// NOINFS-NEXT:    [[CF16_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[CF16]], i32 0, i32 0
+// NOINFS-NEXT:    [[CF16_REAL:%.*]] = load half, ptr [[CF16_REALP]], align 8
+// NOINFS-NEXT:    [[CF16_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[CF16]], i32 0, i32 1
+// NOINFS-NEXT:    [[CF16_IMAG:%.*]] = load half, ptr [[CF16_IMAGP]], align 2
+// NOINFS-NEXT:    store <2 x float> [[TMP6]], ptr [[COERCE]], align 8
+// NOINFS-NEXT:    [[TMP9:%.*]] = load double, ptr [[COERCE]], align 8
+// NOINFS-NEXT:    store <2 x half> [[TMP8]], ptr [[COERCE3]], align 4
+// NOINFS-NEXT:    [[TMP10:%.*]] = load i32, ptr [[COERCE3]], align 4
+// NOINFS-NEXT:    [[COERCE4_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE4]], i32 0, i32 0
+// NOINFS-NEXT:    [[COERCE4_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE4]], i32 0, i32 1
+// NOINFS-NEXT:    store float [[CF32_REAL]], ptr [[COERCE4_REALP]], align 4
+// NOINFS-NEXT:    store float [[CF32_IMAG]], ptr [[COERCE4_IMAGP]], align 4
+// NOINFS-NEXT:    [[TMP11:%.*]] = load <2 x float>, ptr [[COERCE4]], align 4
+// NOINFS-NEXT:    [[INDIRECT_ARG_TEMP_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[INDIRECT_ARG_TEMP]], i32 0, i32 0
+// NOINFS-NEXT:    [[INDIRECT_ARG_TEMP_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[INDIRECT_ARG_TEMP]], i32 0, i32 1
+// NOINFS-NEXT:    store double [[CF64_REAL]], ptr [[INDIRECT_ARG_TEMP_REALP]], align 8
+// NOINFS-NEXT:    store double [[CF64_IMAG]], ptr [[INDIRECT_ARG_TEMP_IMAGP]], align 8
+// NOINFS-NEXT:    [[COERCE5_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[COERCE5]], i32 0, i32 0
+// NOINFS-NEXT:    [[COERCE5_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[COERCE5]], i32 0, i32 1
+// NOINFS-NEXT:    store half [[CF16_REAL]], ptr [[COERCE5_REALP]], align 2
+// NOINFS-NEXT:    store half [[CF16_IMAG]], ptr [[COERCE5_IMAGP]], align 2
+// NOINFS-NEXT:    [[TMP12:%.*]] = load <2 x half>, ptr [[COERCE5]], align 2
+// NOINFS-NEXT:    [[CALL:%.*]] = call ninf float (float, ...) @variadic(float noundef [[TMP2]], double noundef [[CONV]], double noundef [[TMP4]], half noundef [[TMP5]], double noundef [[TMP9]], <2 x double> noundef [[TMP7]], i32 noundef [[TMP10]], <2 x float> noundef [[TMP11]], ptr noundef byval({ double, double }) align 8 [[INDIRECT_ARG_TEMP]], <2 x half> noundef [[TMP12]])
+// NOINFS-NEXT:    ret float [[CALL]]
+//
+float call_variadic(float f32, double f64, _Float16 f16,
+                    float2 v2f32, double2 v2f64, half2 v2f16,
+                    _Complex float cf32, _Complex double cf64, _Complex _Float16 cf16) {
+  return variadic(f32, f32, f64, f16, v2f32, v2f64, v2f16, cf32, cf64, cf16);
+}
+
+// CFINITEONLY: Function Attrs: noinline nounwind optnone
+// CFINITEONLY-LABEL: define dso_local float @call_variadic_indirect
+// CFINITEONLY-SAME: (ptr noundef [[FPTR:%.*]], float noundef [[F32:%.*]], double noundef [[F64:%.*]], half noundef [[F16:%.*]], double noundef [[V2F32_COERCE:%.*]], <2 x double> noundef [[V2F64:%.*]], i32 noundef [[V2F16_COERCE:%.*]], <2 x float> noundef [[CF32_COERCE:%.*]], double noundef [[CF64_COERCE0:%.*]], double noundef [[CF64_COERCE1:%.*]], ptr noundef byval({ half, half }) align 8 [[CF16:%.*]]) #[[ATTR2]] {
+// CFINITEONLY-NEXT:  entry:
+// CFINITEONLY-NEXT:    [[V2F32:%.*]] = alloca <2 x float>, align 8
+// CFINITEONLY-NEXT:    [[V2F16:%.*]] = alloca <2 x half>, align 4
+// CFINITEONLY-NEXT:    [[CF32:%.*]] = alloca { float, float }, align 4
+// CFINITEONLY-NEXT:    [[CF64:%.*]] = alloca { double, double }, align 8
+// CFINITEONLY-NEXT:    [[FPTR_ADDR:%.*]] = alloca ptr, align 8
+// CFINITEONLY-NEXT:    [[F32_ADDR:%.*]] = alloca float, align 4
+// CFINITEONLY-NEXT:    [[F64_ADDR:%.*]] = alloca double, align 8
+// CFINITEONLY-NEXT:    [[F16_ADDR:%.*]] = alloca half, align 2
+// CFINITEONLY-NEXT:    [[V2F32_ADDR:%.*]] = alloca <2 x float>, align 8
+// CFINITEONLY-NEXT:    [[V2F64_ADDR:%.*]] = alloca <2 x double>, align 16
+// CFINITEONLY-NEXT:    [[V2F16_ADDR:%.*]] = alloca <2 x half>, align 4
+// CFINITEONLY-NEXT:    [[COERCE:%.*]] = alloca <2 x float>, align 8
+// CFINITEONLY-NEXT:    [[COERCE3:%.*]] = alloca <2 x half>, align 4
+// CFINITEONLY-NEXT:    [[COERCE4:%.*]] = alloca { float, float }, align 4
+// CFINITEONLY-NEXT:    [[INDIRECT_ARG_TEMP:%.*]] = alloca { double, double }, align 8
+// CFINITEONLY-NEXT:    [[COERCE5:%.*]] = alloca { half, half }, align 2
+// CFINITEONLY-NEXT:    store double [[V2F32_COERCE]], ptr [[V2F32]], align 8
+// CFINITEONLY-NEXT:    [[V2F321:%.*]] = load <2 x float>, ptr [[V2F32]], align 8
+// CFINITEONLY-NEXT:    store i32 [[V2F16_COERCE]], ptr [[V2F16]], align 4
+// CFINITEONLY-NEXT:    [[V2F162:%.*]] = load <2 x half>, ptr [[V2F16]], align 4
+// CFINITEONLY-NEXT:    store <2 x float> [[CF32_COERCE]], ptr [[CF32]], align 4
+// CFINITEONLY-NEXT:    [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 0
+// CFINITEONLY-NEXT:    store double [[CF64_COERCE0]], ptr [[TMP0]], align 8
+// CFINITEONLY-NEXT:    [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 1
+// CFINITEONLY-NEXT:    store double [[CF64_COERCE1]], ptr [[TMP1]], align 8
+// CFINITEONLY-NEXT:    store ptr [[FPTR]], ptr [[FPTR_ADDR]], align 8
+// CFINITEONLY-NEXT:    store float [[F32]], ptr [[F32_ADDR]], align 4
+// CFINITEONLY-NEXT:    store double [[F64]], ptr [[F64_ADDR]], align 8
+// CFINITEONLY-NEXT:    store half [[F16]], ptr [[F16_ADDR]], align 2
+// CFINITEONLY-NEXT:    store <2 x float> [[V2F321]], ptr [[V2F32_ADDR]], align 8
+// CFINITEONLY-NEXT:    store <2 x double> [[V2F64]], ptr [[V2F64_ADDR]], align 16
+// CFINITEONLY-NEXT:    store <2 x half> [[V2F162]], ptr [[V2F16_ADDR]], align 4
+// CFINITEONLY-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[FPTR_ADDR]], align 8
+// CFINITEONLY-NEXT:    [[TMP3:%.*]] = load float, ptr [[F32_ADDR]], align 4
+// CFINITEONLY-NEXT:    [[TMP4:%.*]] = load float, ptr [[F32_ADDR]], align 4
+// CFINITEONLY-NEXT:    [[CONV:%.*]] = fpext float [[TMP4]] to double
+// CFINITEONLY-NEXT:    [[TMP5:%.*]] = load double, ptr [[F64_ADDR]], align 8
+// CFINITEONLY-NEXT:    [[TMP6:%.*]] = load half, ptr [[F16_ADDR]], align 2
+// CFINITEONLY-NEXT:    [[TMP7:%.*]] = load <2 x float>, ptr [[V2F32_ADDR]], align 8
+// CFINITEONLY-NEXT:    [[TMP8:%.*]] = load <2 x double>, ptr [[V2F64_ADDR]], align 16
+// CFINITEONLY-NEXT:    [[TMP9:%.*]] = load <2 x half>, ptr [[V2F16_ADDR]], align 4
+// CFINITEONLY-NEXT:    [[CF32_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[CF32]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[CF32_REAL:%.*]] = load float, ptr [[CF32_REALP]], align 4
+// CFINITEONLY-NEXT:    [[CF32_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[CF32]], i32 0, i32 1
+// CFINITEONLY-NEXT:    [[CF32_IMAG:%.*]] = load float, ptr [[CF32_IMAGP]], align 4
+// CFINITEONLY-NEXT:    [[CF64_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[CF64_REAL:%.*]] = load double, ptr [[CF64_REALP]], align 8
+// CFINITEONLY-NEXT:    [[CF64_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 1
+// CFINITEONLY-NEXT:    [[CF64_IMAG:%.*]] = load double, ptr [[CF64_IMAGP]], align 8
+// CFINITEONLY-NEXT:    [[CF16_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[CF16]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[CF16_REAL:%.*]] = load half, ptr [[CF16_REALP]], align 8
+// CFINITEONLY-NEXT:    [[CF16_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[CF16]], i32 0, i32 1
+// CFINITEONLY-NEXT:    [[CF16_IMAG:%.*]] = load half, ptr [[CF16_IMAGP]], align 2
+// CFINITEONLY-NEXT:    store <2 x float> [[TMP7]], ptr [[COERCE]], align 8
+// CFINITEONLY-NEXT:    [[TMP10:%.*]] = load double, ptr [[COERCE]], align 8
+// CFINITEONLY-NEXT:    store <2 x half> [[TMP9]], ptr [[COERCE3]], align 4
+// CFINITEONLY-NEXT:    [[TMP11:%.*]] = load i32, ptr [[COERCE3]], align 4
+// CFINITEONLY-NEXT:    [[COERCE4_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE4]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[COERCE4_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE4]], i32 0, i32 1
+// CFINITEONLY-NEXT:    store float [[CF32_REAL]], ptr [[COERCE4_REALP]], align 4
+// CFINITEONLY-NEXT:    store float [[CF32_IMAG]], ptr [[COERCE4_IMAGP]], align 4
+// CFINITEONLY-NEXT:    [[TMP12:%.*]] = load <2 x float>, ptr [[COERCE4]], align 4
+// CFINITEONLY-NEXT:    [[INDIRECT_ARG_TEMP_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[INDIRECT_ARG_TEMP]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[INDIRECT_ARG_TEMP_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[INDIRECT_ARG_TEMP]], i32 0, i32 1
+// CFINITEONLY-NEXT:    store double [[CF64_REAL]], ptr [[INDIRECT_ARG_TEMP_REALP]], align 8
+// CFINITEONLY-NEXT:    store double [[CF64_IMAG]], ptr [[INDIRECT_ARG_TEMP_IMAGP]], align 8
+// CFINITEONLY-NEXT:    [[COERCE5_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[COERCE5]], i32 0, i32 0
+// CFINITEONLY-NEXT:    [[COERCE5_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[COERCE5]], i32 0, i32 1
+// CFINITEONLY-NEXT:    store half [[CF16_REAL]], ptr [[COERCE5_REALP]], align 2
+// CFINITEONLY-NEXT:    store half [[CF16_IMAG]], ptr [[COERCE5_IMAGP]], align 2
+// CFINITEONLY-NEXT:    [[TMP13:%.*]] = load <2 x half>, ptr [[COERCE5]], align 2
+// CFINITEONLY-NEXT:    [[CALL:%.*]] = call nnan ninf float (float, ...) [[TMP2]](float noundef [[TMP3]], double noundef [[CONV]], double noundef [[TMP5]], half noundef [[TMP6]], double noundef [[TMP10]], <2 x double> noundef [[TMP8]], i32 noundef [[TMP11]], <2 x float> noundef [[TMP12]], ptr noundef byval({ double, double }) align 8 [[INDIRECT_ARG_TEMP]], <2 x half> noundef [[TMP13]])
+// CFINITEONLY-NEXT:    ret float [[CALL]]
+//
+// CLFINITEONLY: Function Attrs: convergent norecurse nounwind
+// CLFINITEONLY-LABEL: define dso_local float @call_variadic_indirect
+// CLFINITEONLY-SAME: (ptr nocapture noundef readonly [[FPTR:%.*]], float noundef [[F32:%.*]], double noundef [[F64:%.*]], half noundef [[F16:%.*]], double noundef [[V2F32_COERCE:%.*]], <2 x double> noundef [[V2F64:%.*]], i32 noundef [[V2F16_COERCE:%.*]], <2 x float> noundef [[CF32_COERCE:%.*]], double noundef [[CF64_COERCE0:%.*]], double noundef [[CF64_COERCE1:%.*]], ptr nocapture noundef readonly byval({ half, half }) align 8 [[CF16:%.*]]) local_unnamed_addr #[[ATTR5]] {
+// CLFINITEONLY-NEXT:  entry:
+// CLFINITEONLY-NEXT:    [[INDIRECT_ARG_TEMP:%.*]] = alloca { double, double }, align 8
+// CLFINITEONLY-NEXT:    [[CONV:%.*]] = fpext float [[F32]] to double
+// CLFINITEONLY-NEXT:    [[CF16_REAL:%.*]] = load half, ptr [[CF16]], align 8
+// CLFINITEONLY-NEXT:    [[CF16_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[CF16]], i64 0, i32 1
+// CLFINITEONLY-NEXT:    [[CF16_IMAG:%.*]] = load half, ptr [[CF16_IMAGP]], align 2
+// CLFINITEONLY-NEXT:    [[INDIRECT_ARG_TEMP_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[INDIRECT_ARG_TEMP]], i64 0, i32 1
+// CLFINITEONLY-NEXT:    store double [[CF64_COERCE0]], ptr [[INDIRECT_ARG_TEMP]], align 8
+// CLFINITEONLY-NEXT:    store double [[CF64_COERCE1]], ptr [[INDIRECT_ARG_TEMP_IMAGP]], align 8
+// CLFINITEONLY-NEXT:    [[COERCE5_SROA_0_0_VEC_INSERT:%.*]] = insertelement <2 x half> undef, half [[CF16_REAL]], i64 0
+// CLFINITEONLY-NEXT:    [[COERCE5_SROA_0_2_VEC_INSERT:%.*]] = insertelement <2 x half> [[COERCE5_SROA_0_0_VEC_INSERT]], half [[CF16_IMAG]], i64 1
+// CLFINITEONLY-NEXT:    [[CALL:%.*]] = tail call nnan ninf float (float, ...) [[FPTR]](float noundef [[F32]], double noundef [[CONV]], double noundef [[F64]], half noundef [[F16]], double noundef [[V2F32_COERCE]], <2 x double> noundef [[V2F64]], i32 noundef [[V2F16_COERCE]], <2 x float> noundef [[CF32_COERCE]], ptr noundef nonnull byval({ double, double }) align 8 [[INDIRECT_ARG_TEMP]], <2 x half> noundef [[COERCE5_SROA_0_2_VEC_INSERT]]) #[[ATTR10]]
+// CLFINITEONLY-NEXT:    ret float [[CALL]]
+//
+// NONANS: Function Attrs: noinline nounwind optnone
+// NONANS-LABEL: define dso_local float @call_variadic_indirect
+// NONANS-SAME: (ptr noundef [[FPTR:%.*]], float noundef [[F32:%.*]], double noundef [[F64:%.*]], half noundef [[F16:%.*]], double noundef [[V2F32_COERCE:%.*]], <2 x double> noundef [[V2F64:%.*]], i32 noundef [[V2F16_COERCE:%.*]], <2 x float> noundef [[CF32_COERCE:%.*]], double noundef [[CF64_COERCE0:%.*]], double noundef [[CF64_COERCE1:%.*]], ptr noundef byval({ half, half }) align 8 [[CF16:%.*]]) #[[ATTR2]] {
+// NONANS-NEXT:  entry:
+// NONANS-NEXT:    [[V2F32:%.*]] = alloca <2 x float>, align 8
+// NONANS-NEXT:    [[V2F16:%.*]] = alloca <2 x half>, align 4
+// NONANS-NEXT:    [[CF32:%.*]] = alloca { float, float }, align 4
+// NONANS-NEXT:    [[CF64:%.*]] = alloca { double, double }, align 8
+// NONANS-NEXT:    [[FPTR_ADDR:%.*]] = alloca ptr, align 8
+// NONANS-NEXT:    [[F32_ADDR:%.*]] = alloca float, align 4
+// NONANS-NEXT:    [[F64_ADDR:%.*]] = alloca double, align 8
+// NONANS-NEXT:    [[F16_ADDR:%.*]] = alloca half, align 2
+// NONANS-NEXT:    [[V2F32_ADDR:%.*]] = alloca <2 x float>, align 8
+// NONANS-NEXT:    [[V2F64_ADDR:%.*]] = alloca <2 x double>, align 16
+// NONANS-NEXT:    [[V2F16_ADDR:%.*]] = alloca <2 x half>, align 4
+// NONANS-NEXT:    [[COERCE:%.*]] = alloca <2 x float>, align 8
+// NONANS-NEXT:    [[COERCE3:%.*]] = alloca <2 x half>, align 4
+// NONANS-NEXT:    [[COERCE4:%.*]] = alloca { float, float }, align 4
+// NONANS-NEXT:    [[INDIRECT_ARG_TEMP:%.*]] = alloca { double, double }, align 8
+// NONANS-NEXT:    [[COERCE5:%.*]] = alloca { half, half }, align 2
+// NONANS-NEXT:    store double [[V2F32_COERCE]], ptr [[V2F32]], align 8
+// NONANS-NEXT:    [[V2F321:%.*]] = load <2 x float>, ptr [[V2F32]], align 8
+// NONANS-NEXT:    store i32 [[V2F16_COERCE]], ptr [[V2F16]], align 4
+// NONANS-NEXT:    [[V2F162:%.*]] = load <2 x half>, ptr [[V2F16]], align 4
+// NONANS-NEXT:    store <2 x float> [[CF32_COERCE]], ptr [[CF32]], align 4
+// NONANS-NEXT:    [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 0
+// NONANS-NEXT:    store double [[CF64_COERCE0]], ptr [[TMP0]], align 8
+// NONANS-NEXT:    [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 1
+// NONANS-NEXT:    store double [[CF64_COERCE1]], ptr [[TMP1]], align 8
+// NONANS-NEXT:    store ptr [[FPTR]], ptr [[FPTR_ADDR]], align 8
+// NONANS-NEXT:    store float [[F32]], ptr [[F32_ADDR]], align 4
+// NONANS-NEXT:    store double [[F64]], ptr [[F64_ADDR]], align 8
+// NONANS-NEXT:    store half [[F16]], ptr [[F16_ADDR]], align 2
+// NONANS-NEXT:    store <2 x float> [[V2F321]], ptr [[V2F32_ADDR]], align 8
+// NONANS-NEXT:    store <2 x double> [[V2F64]], ptr [[V2F64_ADDR]], align 16
+// NONANS-NEXT:    store <2 x half> [[V2F162]], ptr [[V2F16_ADDR]], align 4
+// NONANS-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[FPTR_ADDR]], align 8
+// NONANS-NEXT:    [[TMP3:%.*]] = load float, ptr [[F32_ADDR]], align 4
+// NONANS-NEXT:    [[TMP4:%.*]] = load float, ptr [[F32_ADDR]], align 4
+// NONANS-NEXT:    [[CONV:%.*]] = fpext float [[TMP4]] to double
+// NONANS-NEXT:    [[TMP5:%.*]] = load double, ptr [[F64_ADDR]], align 8
+// NONANS-NEXT:    [[TMP6:%.*]] = load half, ptr [[F16_ADDR]], align 2
+// NONANS-NEXT:    [[TMP7:%.*]] = load <2 x float>, ptr [[V2F32_ADDR]], align 8
+// NONANS-NEXT:    [[TMP8:%.*]] = load <2 x double>, ptr [[V2F64_ADDR]], align 16
+// NONANS-NEXT:    [[TMP9:%.*]] = load <2 x half>, ptr [[V2F16_ADDR]], align 4
+// NONANS-NEXT:    [[CF32_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[CF32]], i32 0, i32 0
+// NONANS-NEXT:    [[CF32_REAL:%.*]] = load float, ptr [[CF32_REALP]], align 4
+// NONANS-NEXT:    [[CF32_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[CF32]], i32 0, i32 1
+// NONANS-NEXT:    [[CF32_IMAG:%.*]] = load float, ptr [[CF32_IMAGP]], align 4
+// NONANS-NEXT:    [[CF64_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 0
+// NONANS-NEXT:    [[CF64_REAL:%.*]] = load double, ptr [[CF64_REALP]], align 8
+// NONANS-NEXT:    [[CF64_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 1
+// NONANS-NEXT:    [[CF64_IMAG:%.*]] = load double, ptr [[CF64_IMAGP]], align 8
+// NONANS-NEXT:    [[CF16_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[CF16]], i32 0, i32 0
+// NONANS-NEXT:    [[CF16_REAL:%.*]] = load half, ptr [[CF16_REALP]], align 8
+// NONANS-NEXT:    [[CF16_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[CF16]], i32 0, i32 1
+// NONANS-NEXT:    [[CF16_IMAG:%.*]] = load half, ptr [[CF16_IMAGP]], align 2
+// NONANS-NEXT:    store <2 x float> [[TMP7]], ptr [[COERCE]], align 8
+// NONANS-NEXT:    [[TMP10:%.*]] = load double, ptr [[COERCE]], align 8
+// NONANS-NEXT:    store <2 x half> [[TMP9]], ptr [[COERCE3]], align 4
+// NONANS-NEXT:    [[TMP11:%.*]] = load i32, ptr [[COERCE3]], align 4
+// NONANS-NEXT:    [[COERCE4_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE4]], i32 0, i32 0
+// NONANS-NEXT:    [[COERCE4_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE4]], i32 0, i32 1
+// NONANS-NEXT:    store float [[CF32_REAL]], ptr [[COERCE4_REALP]], align 4
+// NONANS-NEXT:    store float [[CF32_IMAG]], ptr [[COERCE4_IMAGP]], align 4
+// NONANS-NEXT:    [[TMP12:%.*]] = load <2 x float>, ptr [[COERCE4]], align 4
+// NONANS-NEXT:    [[INDIRECT_ARG_TEMP_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[INDIRECT_ARG_TEMP]], i32 0, i32 0
+// NONANS-NEXT:    [[INDIRECT_ARG_TEMP_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[INDIRECT_ARG_TEMP]], i32 0, i32 1
+// NONANS-NEXT:    store double [[CF64_REAL]], ptr [[INDIRECT_ARG_TEMP_REALP]], align 8
+// NONANS-NEXT:    store double [[CF64_IMAG]], ptr [[INDIRECT_ARG_TEMP_IMAGP]], align 8
+// NONANS-NEXT:    [[COERCE5_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[COERCE5]], i32 0, i32 0
+// NONANS-NEXT:    [[COERCE5_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[COERCE5]], i32 0, i32 1
+// NONANS-NEXT:    store half [[CF16_REAL]], ptr [[COERCE5_REALP]], align 2
+// NONANS-NEXT:    store half [[CF16_IMAG]], ptr [[COERCE5_IMAGP]], align 2
+// NONANS-NEXT:    [[TMP13:%.*]] = load <2 x half>, ptr [[COERCE5]], align 2
+// NONANS-NEXT:    [[CALL:%.*]] = call nnan float (float, ...) [[TMP2]](float noundef [[TMP3]], double noundef [[CONV]], double noundef [[TMP5]], half noundef [[TMP6]], double noundef [[TMP10]], <2 x double> noundef [[TMP8]], i32 noundef [[TMP11]], <2 x float> noundef [[TMP12]], ptr noundef byval({ double, double }) align 8 [[INDIRECT_ARG_TEMP]], <2 x half> noundef [[TMP13]])
+// NONANS-NEXT:    ret float [[CALL]]
+//
+// NOINFS: Function Attrs: noinline nounwind optnone
+// NOINFS-LABEL: define dso_local float @call_variadic_indirect
+// NOINFS-SAME: (ptr noundef [[FPTR:%.*]], float noundef [[F32:%.*]], double noundef [[F64:%.*]], half noundef [[F16:%.*]], double noundef [[V2F32_COERCE:%.*]], <2 x double> noundef [[V2F64:%.*]], i32 noundef [[V2F16_COERCE:%.*]], <2 x float> noundef [[CF32_COERCE:%.*]], double noundef [[CF64_COERCE0:%.*]], double noundef [[CF64_COERCE1:%.*]], ptr noundef byval({ half, half }) align 8 [[CF16:%.*]]) #[[ATTR2]] {
+// NOINFS-NEXT:  entry:
+// NOINFS-NEXT:    [[V2F32:%.*]] = alloca <2 x float>, align 8
+// NOINFS-NEXT:    [[V2F16:%.*]] = alloca <2 x half>, align 4
+// NOINFS-NEXT:    [[CF32:%.*]] = alloca { float, float }, align 4
+// NOINFS-NEXT:    [[CF64:%.*]] = alloca { double, double }, align 8
+// NOINFS-NEXT:    [[FPTR_ADDR:%.*]] = alloca ptr, align 8
+// NOINFS-NEXT:    [[F32_ADDR:%.*]] = alloca float, align 4
+// NOINFS-NEXT:    [[F64_ADDR:%.*]] = alloca double, align 8
+// NOINFS-NEXT:    [[F16_ADDR:%.*]] = alloca half, align 2
+// NOINFS-NEXT:    [[V2F32_ADDR:%.*]] = alloca <2 x float>, align 8
+// NOINFS-NEXT:    [[V2F64_ADDR:%.*]] = alloca <2 x double>, align 16
+// NOINFS-NEXT:    [[V2F16_ADDR:%.*]] = alloca <2 x half>, align 4
+// NOINFS-NEXT:    [[COERCE:%.*]] = alloca <2 x float>, align 8
+// NOINFS-NEXT:    [[COERCE3:%.*]] = alloca <2 x half>, align 4
+// NOINFS-NEXT:    [[COERCE4:%.*]] = alloca { float, float }, align 4
+// NOINFS-NEXT:    [[INDIRECT_ARG_TEMP:%.*]] = alloca { double, double }, align 8
+// NOINFS-NEXT:    [[COERCE5:%.*]] = alloca { half, half }, align 2
+// NOINFS-NEXT:    store double [[V2F32_COERCE]], ptr [[V2F32]], align 8
+// NOINFS-NEXT:    [[V2F321:%.*]] = load <2 x float>, ptr [[V2F32]], align 8
+// NOINFS-NEXT:    store i32 [[V2F16_COERCE]], ptr [[V2F16]], align 4
+// NOINFS-NEXT:    [[V2F162:%.*]] = load <2 x half>, ptr [[V2F16]], align 4
+// NOINFS-NEXT:    store <2 x float> [[CF32_COERCE]], ptr [[CF32]], align 4
+// NOINFS-NEXT:    [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 0
+// NOINFS-NEXT:    store double [[CF64_COERCE0]], ptr [[TMP0]], align 8
+// NOINFS-NEXT:    [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 1
+// NOINFS-NEXT:    store double [[CF64_COERCE1]], ptr [[TMP1]], align 8
+// NOINFS-NEXT:    store ptr [[FPTR]], ptr [[FPTR_ADDR]], align 8
+// NOINFS-NEXT:    store float [[F32]], ptr [[F32_ADDR]], align 4
+// NOINFS-NEXT:    store double [[F64]], ptr [[F64_ADDR]], align 8
+// NOINFS-NEXT:    store half [[F16]], ptr [[F16_ADDR]], align 2
+// NOINFS-NEXT:    store <2 x float> [[V2F321]], ptr [[V2F32_ADDR]], align 8
+// NOINFS-NEXT:    store <2 x double> [[V2F64]], ptr [[V2F64_ADDR]], align 16
+// NOINFS-NEXT:    store <2 x half> [[V2F162]], ptr [[V2F16_ADDR]], align 4
+// NOINFS-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[FPTR_ADDR]], align 8
+// NOINFS-NEXT:    [[TMP3:%.*]] = load float, ptr [[F32_ADDR]], align 4
+// NOINFS-NEXT:    [[TMP4:%.*]] = load float, ptr [[F32_ADDR]], align 4
+// NOINFS-NEXT:    [[CONV:%.*]] = fpext float [[TMP4]] to double
+// NOINFS-NEXT:    [[TMP5:%.*]] = load double, ptr [[F64_ADDR]], align 8
+// NOINFS-NEXT:    [[TMP6:%.*]] = load half, ptr [[F16_ADDR]], align 2
+// NOINFS-NEXT:    [[TMP7:%.*]] = load <2 x float>, ptr [[V2F32_ADDR]], align 8
+// NOINFS-NEXT:    [[TMP8:%.*]] = load <2 x double>, ptr [[V2F64_ADDR]], align 16
+// NOINFS-NEXT:    [[TMP9:%.*]] = load <2 x half>, ptr [[V2F16_ADDR]], align 4
+// NOINFS-NEXT:    [[CF32_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[CF32]], i32 0, i32 0
+// NOINFS-NEXT:    [[CF32_REAL:%.*]] = load float, ptr [[CF32_REALP]], align 4
+// NOINFS-NEXT:    [[CF32_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[CF32]], i32 0, i32 1
+// NOINFS-NEXT:    [[CF32_IMAG:%.*]] = load float, ptr [[CF32_IMAGP]], align 4
+// NOINFS-NEXT:    [[CF64_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 0
+// NOINFS-NEXT:    [[CF64_REAL:%.*]] = load double, ptr [[CF64_REALP]], align 8
+// NOINFS-NEXT:    [[CF64_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[CF64]], i32 0, i32 1
+// NOINFS-NEXT:    [[CF64_IMAG:%.*]] = load double, ptr [[CF64_IMAGP]], align 8
+// NOINFS-NEXT:    [[CF16_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[CF16]], i32 0, i32 0
+// NOINFS-NEXT:    [[CF16_REAL:%.*]] = load half, ptr [[CF16_REALP]], align 8
+// NOINFS-NEXT:    [[CF16_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[CF16]], i32 0, i32 1
+// NOINFS-NEXT:    [[CF16_IMAG:%.*]] = load half, ptr [[CF16_IMAGP]], align 2
+// NOINFS-NEXT:    store <2 x float> [[TMP7]], ptr [[COERCE]], align 8
+// NOINFS-NEXT:    [[TMP10:%.*]] = load double, ptr [[COERCE]], align 8
+// NOINFS-NEXT:    store <2 x half> [[TMP9]], ptr [[COERCE3]], align 4
+// NOINFS-NEXT:    [[TMP11:%.*]] = load i32, ptr [[COERCE3]], align 4
+// NOINFS-NEXT:    [[COERCE4_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE4]], i32 0, i32 0
+// NOINFS-NEXT:    [[COERCE4_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE4]], i32 0, i32 1
+// NOINFS-NEXT:    store float [[CF32_REAL]], ptr [[COERCE4_REALP]], align 4
+// NOINFS-NEXT:    store float [[CF32_IMAG]], ptr [[COERCE4_IMAGP]], align 4
+// NOINFS-NEXT:    [[TMP12:%.*]] = load <2 x float>, ptr [[COERCE4]], align 4
+// NOINFS-NEXT:    [[INDIRECT_ARG_TEMP_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[INDIRECT_ARG_TEMP]], i32 0, i32 0
+// NOINFS-NEXT:    [[INDIRECT_ARG_TEMP_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[INDIRECT_ARG_TEMP]], i32 0, i32 1
+// NOINFS-NEXT:    store double [[CF64_REAL]], ptr [[INDIRECT_ARG_TEMP_REALP]], align 8
+// NOINFS-NEXT:    store double [[CF64_IMAG]], ptr [[INDIRECT_ARG_TEMP_IMAGP]], align 8
+// NOINFS-NEXT:    [[COERCE5_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[COERCE5]], i32 0, i32 0
+// NOINFS-NEXT:    [[COERCE5_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[COERCE5]], i32 0, i32 1
+// NOINFS-NEXT:    store half [[CF16_REAL]], ptr [[COERCE5_REALP]], align 2
+// NOINFS-NEXT:    store half [[CF16_IMAG]], ptr [[COERCE5_IMAGP]], align 2
+// NOINFS-NEXT:    [[TMP13:%.*]] = load <2 x half>, ptr [[COERCE5]], align 2
+// NOINFS-NEXT:    [[CALL:%.*]] = call ninf float (float, ...) [[TMP2]](float noundef [[TMP3]], double noundef [[CONV]], double noundef [[TMP5]], half noundef [[TMP6]], double noundef [[TMP10]], <2 x double> noundef [[TMP8]], i32 noundef [[TMP11]], <2 x float> noundef [[TMP12]], ptr noundef byval({ double, double }) align 8 [[INDIRECT_ARG_TEMP]], <2 x half> noundef [[TMP13]])
+// NOINFS-NEXT:    ret float [[CALL]]
+//
+float call_variadic_indirect(float fptr(float, ...), float f32, double f64, _Float16 f16,
+                             float2 v2f32, double2 v2f64, half2 v2f16,
+                             _Complex float cf32, _Complex double cf64, _Complex _Float16 cf16) {
+  return (*fptr)(f32, f32, f64, f16, v2f32, v2f64, v2f16, cf32, cf64, cf16);
+}
+
+typedef __attribute__((__vector_size__(4 * sizeof(double)))) double __m256d;
+extern __m256d extern_m256d(__m256d, ...);
+
+// CFINITEONLY: Function Attrs: noinline nounwind optnone
+// CFINITEONLY-LABEL: define dso_local <4 x double> @call_m256d
+// CFINITEONLY-SAME: (<4 x double> noundef [[X:%.*]]) #[[ATTR5:[0-9]+]] {
+// CFINITEONLY-NEXT:  entry:
+// CFINITEONLY-NEXT:    [[X_ADDR:%.*]] = alloca <4 x double>, align 32
+// CFINITEONLY-NEXT:    store <4 x double> [[X]], ptr [[X_ADDR]], align 32
+// CFINITEONLY-NEXT:    [[TMP0:%.*]] = load <4 x double>, ptr [[X_ADDR]], align 32
+// CFINITEONLY-NEXT:    [[TMP1:%.*]] = load <4 x double>, ptr [[X_ADDR]], align 32
+// CFINITEONLY-NEXT:    [[CALL:%.*]] = call nnan ninf <4 x double> (<4 x double>, ...) @extern_m256d(<4 x double> noundef [[TMP0]], <4 x double> noundef [[TMP1]])
+// CFINITEONLY-NEXT:    ret <4 x double> [[CALL]]
+//
+// CLFINITEONLY: Function Attrs: convergent norecurse nounwind
+// CLFINITEONLY-LABEL: define dso_local <4 x double> @call_m256d
+// CLFINITEONLY-SAME: (<4 x double> noundef [[X:%.*]]) local_unnamed_addr #[[ATTR8:[0-9]+]] {
+// CLFINITEONLY-NEXT:  entry:
+// CLFINITEONLY-NEXT:    [[CALL:%.*]] = tail call nnan ninf <4 x double> (<4 x double>, ...) @extern_m256d(<4 x double> noundef [[X]], <4 x double> noundef [[X]]) #[[ATTR10]]
+// CLFINITEONLY-NEXT:    ret <4 x double> [[CALL]]
+//
+// NONANS: Function Attrs: noinline nounwind optnone
+// NONANS-LABEL: define dso_local <4 x double> @call_m256d
+// NONANS-SAME: (<4 x double> noundef [[X:%.*]]) #[[ATTR5:[0-9]+]] {
+// NONANS-NEXT:  entry:
+// NONANS-NEXT:    [[X_ADDR:%.*]] = alloca <4 x double>, align 32
+// NONANS-NEXT:    store <4 x double> [[X]], ptr [[X_ADDR]], align 32
+// NONANS-NEXT:    [[TMP0:%.*]] = load <4 x double>, ptr [[X_ADDR]], align 32
+// NONANS-NEXT:    [[TMP1:%.*]] = load <4 x double>, ptr [[X_ADDR]], align 32
+// NONANS-NEXT:    [[CALL:%.*]] = call nnan <4 x double> (<4 x double>, ...) @extern_m256d(<4 x double> noundef [[TMP0]], <4 x double> noundef [[TMP1]])
+// NONANS-NEXT:    ret <4 x double> [[CALL]]
+//
+// NOINFS: Function Attrs: noinline nounwind optnone
+// NOINFS-LABEL: define dso_local <4 x double> @call_m256d
+// NOINFS-SAME: (<4 x double> noundef [[X:%.*]]) #[[ATTR5:[0-9]+]] {
+// NOINFS-NEXT:  entry:
+// NOINFS-NEXT:    [[X_ADDR:%.*]] = alloca <4 x double>, align 32
+// NOINFS-NEXT:    store <4 x double> [[X]], ptr [[X_ADDR]], align 32
+// NOINFS-NEXT:    [[TMP0:%.*]] = load <4 x double>, ptr [[X_ADDR]], align 32
+// NOINFS-NEXT:    [[TMP1:%.*]] = load <4 x double>, ptr [[X_ADDR]], align 32
+// NOINFS-NEXT:    [[CALL:%.*]] = call ninf <4 x double> (<4 x double>, ...) @extern_m256d(<4 x double> noundef [[TMP0]], <4 x double> noundef [[TMP1]])
+// NOINFS-NEXT:    ret <4 x double> [[CALL]]
+//
+__m256d call_m256d(__m256d x) {
+  return extern_m256d(x, x);
+}
+
+// CFINITEONLY: Function Attrs: noinline nounwind optnone
+// CFINITEONLY-LABEL: define dso_local <25 x double> @call_matrix
+// CFINITEONLY-SAME: (<25 x double> noundef [[X:%.*]]) #[[ATTR6:[0-9]+]] {
+// CFINITEONLY-NEXT:  entry:
+// CFINITEONLY-NEXT:    [[X_ADDR:%.*]] = alloca [25 x double], align 8
+// CFINITEONLY-NEXT:    store <25 x double> [[X]], ptr [[X_ADDR]], align 8
+// CFINITEONLY-NEXT:    [[TMP0:%.*]] = load <25 x double>, ptr [[X_ADDR]], align 8
+// CFINITEONLY-NEXT:    [[CALL:%.*]] = call nnan ninf <25 x double> @extern_matrix(<25 x double> noundef [[TMP0]])
+// CFINITEONLY-NEXT:    ret <25 x double> [[CALL]]
+//
+// CLFINITEONLY: Function Attrs: convergent norecurse nounwind
+// CLFINITEONLY-LABEL: define dso_local <25 x double> @call_matrix
+// CLFINITEONLY-SAME: (<25 x double> noundef [[X:%.*]]) local_unnamed_addr #[[ATTR9:[0-9]+]] {
+// CLFINITEONLY-NEXT:  entry:
+// CLFINITEONLY-NEXT:    [[CALL:%.*]] = tail call nnan ninf <25 x double> @extern_matrix(<25 x double> noundef [[X]]) #[[ATTR10]]
+// CLFINITEONLY-NEXT:    ret <25 x double> [[CALL]]
+//
+// NONANS: Function Attrs: noinline nounwind optnone
+// NONANS-LABEL: define dso_local <25 x double> @call_matrix
+// NONANS-SAME: (<25 x double> noundef [[X:%.*]]) #[[ATTR6:[0-9]+]] {
+// NONANS-NEXT:  entry:
+// NONANS-NEXT:    [[X_ADDR:%.*]] = alloca [25 x double], align 8
+// NONANS-NEXT:    store <25 x double> [[X]], ptr [[X_ADDR]], align 8
+// NONANS-NEXT:    [[TMP0:%.*]] = load <25 x double>, ptr [[X_ADDR]], align 8
+// NONANS-NEXT:    [[CALL:%.*]] = call nnan <25 x double> @extern_matrix(<25 x double> noundef [[TMP0]])
+// NONANS-NEXT:    ret <25 x double> [[CALL]]
+//
+// NOINFS: Function Attrs: noinline nounwind optnone
+// NOINFS-LABEL: define dso_local <25 x double> @call_matrix
+// NOINFS-SAME: (<25 x double> noundef [[X:%.*]]) #[[ATTR6:[0-9]+]] {
+// NOINFS-NEXT:  entry:
+// NOINFS-NEXT:    [[X_ADDR:%.*]] = alloca [25 x double], align 8
+// NOINFS-NEXT:    store <25 x double> [[X]], ptr [[X_ADDR]], align 8
+// NOINFS-NEXT:    [[TMP0:%.*]] = load <25 x double>, ptr [[X_ADDR]], align 8
+// NOINFS-NEXT:    [[CALL:%.*]] = call ninf <25 x double> @extern_matrix(<25 x double> noundef [[TMP0]])
+// NOINFS-NEXT:    ret <25 x double> [[CALL]]
+//
+dx5x5_t call_matrix(dx5x5_t x) {
+  return extern_matrix(x);
+}


        


More information about the cfe-commits mailing list