llvm/clang/test/CodeGen/nofpclass.c

// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes --version 2
// REQUIRES: x86-registered-target
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-feature +avx -fenable-matrix -menable-no-infs -menable-no-nans -emit-llvm -o - %s | FileCheck -check-prefixes=CFINITEONLY %s
// RUN: %clang_cc1 -x cl -triple x86_64-unknown-unknown -target-feature +avx -fenable-matrix -menable-no-nans -menable-no-infs -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 nofpclass(nan inf) float @defined_func_f32
// CFINITEONLY-SAME: (float noundef nofpclass(nan inf) [[A:%.*]], float noundef nofpclass(nan inf) [[B:%.*]], float noundef nofpclass(nan inf) [[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 nofpclass(nan inf) float @defined_func_f32
// CLFINITEONLY-SAME: (float noundef nofpclass(nan inf) [[A:%.*]], float noundef nofpclass(nan inf) [[B:%.*]], float noundef nofpclass(nan inf) [[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 nofpclass(nan) float @defined_func_f32
// NONANS-SAME: (float noundef nofpclass(nan) [[A:%.*]], float noundef nofpclass(nan) [[B:%.*]], float noundef nofpclass(nan) [[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 nofpclass(inf) float @defined_func_f32
// NOINFS-SAME: (float noundef nofpclass(inf) [[A:%.*]], float noundef nofpclass(inf) [[B:%.*]], float noundef nofpclass(inf) [[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 nofpclass(nan inf) <2 x double> @defined_func_v2f64
// CFINITEONLY-SAME: (<2 x double> noundef nofpclass(nan inf) [[A:%.*]], <2 x double> noundef nofpclass(nan inf) [[B:%.*]], <2 x double> noundef nofpclass(nan inf) [[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 nofpclass(nan inf) <2 x double> @defined_func_v2f64
// CLFINITEONLY-SAME: (<2 x double> noundef nofpclass(nan inf) [[A:%.*]], <2 x double> noundef nofpclass(nan inf) [[B:%.*]], <2 x double> noundef nofpclass(nan inf) [[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 nofpclass(nan) <2 x double> @defined_func_v2f64
// NONANS-SAME: (<2 x double> noundef nofpclass(nan) [[A:%.*]], <2 x double> noundef nofpclass(nan) [[B:%.*]], <2 x double> noundef nofpclass(nan) [[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 nofpclass(inf) <2 x double> @defined_func_v2f64
// NOINFS-SAME: (<2 x double> noundef nofpclass(inf) [[A:%.*]], <2 x double> noundef nofpclass(inf) [[B:%.*]], <2 x double> noundef nofpclass(inf) [[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 nofpclass(nan inf) float @call_extern_func
// CFINITEONLY-SAME: (float noundef nofpclass(nan inf) [[A:%.*]], double noundef nofpclass(nan inf) [[B:%.*]], half noundef nofpclass(nan inf) [[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 nofpclass(nan inf) float @extern_func(float noundef nofpclass(nan inf) [[TMP0]], double noundef nofpclass(nan inf) [[TMP1]], half noundef nofpclass(nan inf) [[TMP2]])
// CFINITEONLY-NEXT:    ret float [[CALL]]
//
// CLFINITEONLY: Function Attrs: convergent norecurse nounwind
// CLFINITEONLY-LABEL: define dso_local nofpclass(nan inf) float @call_extern_func
// CLFINITEONLY-SAME: (float noundef nofpclass(nan inf) [[A:%.*]], double noundef nofpclass(nan inf) [[B:%.*]], half noundef nofpclass(nan inf) [[C:%.*]]) local_unnamed_addr #[[ATTR3:[0-9]+]] {
// CLFINITEONLY-NEXT:  entry:
// CLFINITEONLY-NEXT:    [[CALL:%.*]] = tail call nnan ninf nofpclass(nan inf) float @extern_func(float noundef nofpclass(nan inf) [[A]], double noundef nofpclass(nan inf) [[B]], half noundef nofpclass(nan inf) [[C]]) #[[ATTR11:[0-9]+]]
// CLFINITEONLY-NEXT:    ret float [[CALL]]
//
// NONANS: Function Attrs: noinline nounwind optnone
// NONANS-LABEL: define dso_local nofpclass(nan) float @call_extern_func
// NONANS-SAME: (float noundef nofpclass(nan) [[A:%.*]], double noundef nofpclass(nan) [[B:%.*]], half noundef nofpclass(nan) [[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 nofpclass(nan) float @extern_func(float noundef nofpclass(nan) [[TMP0]], double noundef nofpclass(nan) [[TMP1]], half noundef nofpclass(nan) [[TMP2]])
// NONANS-NEXT:    ret float [[CALL]]
//
// NOINFS: Function Attrs: noinline nounwind optnone
// NOINFS-LABEL: define dso_local nofpclass(inf) float @call_extern_func
// NOINFS-SAME: (float noundef nofpclass(inf) [[A:%.*]], double noundef nofpclass(inf) [[B:%.*]], half noundef nofpclass(inf) [[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 nofpclass(inf) float @extern_func(float noundef nofpclass(inf) [[TMP0]], double noundef nofpclass(inf) [[TMP1]], half noundef nofpclass(inf) [[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 nofpclass(nan inf) double @call_extern_func_vec
// CFINITEONLY-SAME: (double noundef nofpclass(nan inf) [[A_COERCE:%.*]], <2 x double> noundef nofpclass(nan inf) [[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 nofpclass(nan inf) double @extern_func_vec(double noundef nofpclass(nan inf) [[TMP3]], <2 x double> noundef nofpclass(nan inf) [[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 nofpclass(nan inf) double @call_extern_func_vec
// CLFINITEONLY-SAME: (double noundef nofpclass(nan inf) [[A_COERCE:%.*]], <2 x double> noundef nofpclass(nan inf) [[B:%.*]], i32 noundef [[C_COERCE:%.*]]) local_unnamed_addr #[[ATTR5:[0-9]+]] {
// CLFINITEONLY-NEXT:  entry:
// CLFINITEONLY-NEXT:    [[CALL:%.*]] = tail call nnan ninf nofpclass(nan inf) double @extern_func_vec(double noundef nofpclass(nan inf) [[A_COERCE]], <2 x double> noundef nofpclass(nan inf) [[B]], i32 noundef [[C_COERCE]]) #[[ATTR11]]
// CLFINITEONLY-NEXT:    ret double [[CALL]]
//
// NONANS: Function Attrs: noinline nounwind optnone
// NONANS-LABEL: define dso_local nofpclass(nan) double @call_extern_func_vec
// NONANS-SAME: (double noundef nofpclass(nan) [[A_COERCE:%.*]], <2 x double> noundef nofpclass(nan) [[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 nofpclass(nan) double @extern_func_vec(double noundef nofpclass(nan) [[TMP3]], <2 x double> noundef nofpclass(nan) [[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 nofpclass(inf) double @call_extern_func_vec
// NOINFS-SAME: (double noundef nofpclass(inf) [[A_COERCE:%.*]], <2 x double> noundef nofpclass(inf) [[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 nofpclass(inf) double @extern_func_vec(double noundef nofpclass(inf) [[TMP3]], <2 x double> noundef nofpclass(inf) [[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 nofpclass(nan inf) <2 x float> @defined_complex_func
// CFINITEONLY-SAME: (<2 x float> noundef nofpclass(nan inf) [[A_COERCE:%.*]], double noundef nofpclass(nan inf) [[B_COERCE0:%.*]], double noundef nofpclass(nan inf) [[B_COERCE1:%.*]], <2 x half> noundef nofpclass(nan inf) [[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 nuw { double, double }, ptr [[B]], i32 0, i32 0
// CFINITEONLY-NEXT:    store double [[B_COERCE0]], ptr [[TMP0]], align 8
// CFINITEONLY-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { float, float }, ptr [[COERCE]], i32 0, i32 0
// CFINITEONLY-NEXT:    [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nuw { double, double }, ptr [[COERCE1]], i32 0, i32 0
// CFINITEONLY-NEXT:    [[COERCE1_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nuw { double, double }, ptr [[COERCE1]], i32 0, i32 0
// CFINITEONLY-NEXT:    [[TMP4:%.*]] = load double, ptr [[TMP3]], align 8
// CFINITEONLY-NEXT:    [[TMP5:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE1]], i32 0, i32 1
// CFINITEONLY-NEXT:    [[TMP6:%.*]] = load double, ptr [[TMP5]], align 8
// CFINITEONLY-NEXT:    [[COERCE2_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[COERCE2]], i32 0, i32 0
// CFINITEONLY-NEXT:    [[COERCE2_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nofpclass(nan inf) <2 x float> @extern_complex(<2 x float> noundef nofpclass(nan inf) [[TMP2]], double noundef nofpclass(nan inf) [[TMP4]], double noundef nofpclass(nan inf) [[TMP6]], <2 x half> noundef nofpclass(nan inf) [[TMP7]])
// CFINITEONLY-NEXT:    store <2 x float> [[CALL]], ptr [[COERCE3]], align 4
// CFINITEONLY-NEXT:    [[COERCE3_REALP:%.*]] = getelementptr inbounds nuw { 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 nuw { 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 nuw { float, float }, ptr [[RETVAL]], i32 0, i32 0
// CFINITEONLY-NEXT:    [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nofpclass(nan inf) <2 x float> @defined_complex_func
// CLFINITEONLY-SAME: (<2 x float> noundef nofpclass(nan inf) [[A_COERCE:%.*]], double noundef nofpclass(nan inf) [[B_COERCE0:%.*]], double noundef nofpclass(nan inf) [[B_COERCE1:%.*]], <2 x half> noundef nofpclass(nan inf) [[C_COERCE:%.*]]) local_unnamed_addr #[[ATTR6:[0-9]+]] {
// CLFINITEONLY-NEXT:  entry:
// CLFINITEONLY-NEXT:    [[CALL:%.*]] = tail call nnan ninf nofpclass(nan inf) <2 x float> @extern_complex(<2 x float> noundef nofpclass(nan inf) [[A_COERCE]], double noundef nofpclass(nan inf) [[B_COERCE0]], double noundef nofpclass(nan inf) [[B_COERCE1]], <2 x half> noundef nofpclass(nan inf) [[C_COERCE]]) #[[ATTR11]]
// CLFINITEONLY-NEXT:    ret <2 x float> [[CALL]]
//
// NONANS: Function Attrs: noinline nounwind optnone
// NONANS-LABEL: define dso_local nofpclass(nan) <2 x float> @defined_complex_func
// NONANS-SAME: (<2 x float> noundef nofpclass(nan) [[A_COERCE:%.*]], double noundef nofpclass(nan) [[B_COERCE0:%.*]], double noundef nofpclass(nan) [[B_COERCE1:%.*]], <2 x half> noundef nofpclass(nan) [[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 nuw { double, double }, ptr [[B]], i32 0, i32 0
// NONANS-NEXT:    store double [[B_COERCE0]], ptr [[TMP0]], align 8
// NONANS-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { float, float }, ptr [[COERCE]], i32 0, i32 0
// NONANS-NEXT:    [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nuw { double, double }, ptr [[COERCE1]], i32 0, i32 0
// NONANS-NEXT:    [[COERCE1_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nuw { double, double }, ptr [[COERCE1]], i32 0, i32 0
// NONANS-NEXT:    [[TMP4:%.*]] = load double, ptr [[TMP3]], align 8
// NONANS-NEXT:    [[TMP5:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE1]], i32 0, i32 1
// NONANS-NEXT:    [[TMP6:%.*]] = load double, ptr [[TMP5]], align 8
// NONANS-NEXT:    [[COERCE2_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[COERCE2]], i32 0, i32 0
// NONANS-NEXT:    [[COERCE2_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nofpclass(nan) <2 x float> @extern_complex(<2 x float> noundef nofpclass(nan) [[TMP2]], double noundef nofpclass(nan) [[TMP4]], double noundef nofpclass(nan) [[TMP6]], <2 x half> noundef nofpclass(nan) [[TMP7]])
// NONANS-NEXT:    store <2 x float> [[CALL]], ptr [[COERCE3]], align 4
// NONANS-NEXT:    [[COERCE3_REALP:%.*]] = getelementptr inbounds nuw { 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 nuw { 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 nuw { float, float }, ptr [[RETVAL]], i32 0, i32 0
// NONANS-NEXT:    [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nofpclass(inf) <2 x float> @defined_complex_func
// NOINFS-SAME: (<2 x float> noundef nofpclass(inf) [[A_COERCE:%.*]], double noundef nofpclass(inf) [[B_COERCE0:%.*]], double noundef nofpclass(inf) [[B_COERCE1:%.*]], <2 x half> noundef nofpclass(inf) [[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 nuw { double, double }, ptr [[B]], i32 0, i32 0
// NOINFS-NEXT:    store double [[B_COERCE0]], ptr [[TMP0]], align 8
// NOINFS-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { float, float }, ptr [[COERCE]], i32 0, i32 0
// NOINFS-NEXT:    [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nuw { double, double }, ptr [[COERCE1]], i32 0, i32 0
// NOINFS-NEXT:    [[COERCE1_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nuw { double, double }, ptr [[COERCE1]], i32 0, i32 0
// NOINFS-NEXT:    [[TMP4:%.*]] = load double, ptr [[TMP3]], align 8
// NOINFS-NEXT:    [[TMP5:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[COERCE1]], i32 0, i32 1
// NOINFS-NEXT:    [[TMP6:%.*]] = load double, ptr [[TMP5]], align 8
// NOINFS-NEXT:    [[COERCE2_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[COERCE2]], i32 0, i32 0
// NOINFS-NEXT:    [[COERCE2_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nofpclass(inf) <2 x float> @extern_complex(<2 x float> noundef nofpclass(inf) [[TMP2]], double noundef nofpclass(inf) [[TMP4]], double noundef nofpclass(inf) [[TMP6]], <2 x half> noundef nofpclass(inf) [[TMP7]])
// NOINFS-NEXT:    store <2 x float> [[CALL]], ptr [[COERCE3]], align 4
// NOINFS-NEXT:    [[COERCE3_REALP:%.*]] = getelementptr inbounds nuw { 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 nuw { 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 nuw { float, float }, ptr [[RETVAL]], i32 0, i32 0
// NOINFS-NEXT:    [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nofpclass(nan inf) { double, double } @defined_complex_func_f64_ret
// CFINITEONLY-SAME: (double noundef nofpclass(nan inf) [[C_COERCE0:%.*]], double noundef nofpclass(nan inf) [[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 nuw { double, double }, ptr [[C]], i32 0, i32 0
// CFINITEONLY-NEXT:    store double [[C_COERCE0]], ptr [[TMP0]], align 8
// CFINITEONLY-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[C]], i32 0, i32 1
// CFINITEONLY-NEXT:    store double [[C_COERCE1]], ptr [[TMP1]], align 8
// CFINITEONLY-NEXT:    [[C_REALP:%.*]] = getelementptr inbounds nuw { 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 nuw { 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 nuw { 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 nuw { 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 nnan ninf nofpclass(nan inf) { double, double } @__muldc3(double noundef nofpclass(nan inf) [[C_REAL]], double noundef nofpclass(nan inf) [[C_IMAG]], double noundef nofpclass(nan inf) [[C_REAL2]], double noundef nofpclass(nan inf) [[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 nuw { double, double }, ptr [[RETVAL]], i32 0, i32 0
// CFINITEONLY-NEXT:    [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nofpclass(nan inf) { double, double } @defined_complex_func_f64_ret
// CLFINITEONLY-SAME: (double noundef nofpclass(nan inf) [[C_COERCE0:%.*]], double noundef nofpclass(nan inf) [[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 nofpclass(nan) { double, double } @defined_complex_func_f64_ret
// NONANS-SAME: (double noundef nofpclass(nan) [[C_COERCE0:%.*]], double noundef nofpclass(nan) [[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 nuw { double, double }, ptr [[C]], i32 0, i32 0
// NONANS-NEXT:    store double [[C_COERCE0]], ptr [[TMP0]], align 8
// NONANS-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[C]], i32 0, i32 1
// NONANS-NEXT:    store double [[C_COERCE1]], ptr [[TMP1]], align 8
// NONANS-NEXT:    [[C_REALP:%.*]] = getelementptr inbounds nuw { 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 nuw { 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 nuw { 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 nuw { 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 nnan nofpclass(nan) { double, double } @__muldc3(double noundef nofpclass(nan) [[C_REAL]], double noundef nofpclass(nan) [[C_IMAG]], double noundef nofpclass(nan) [[C_REAL2]], double noundef nofpclass(nan) [[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 nuw { double, double }, ptr [[RETVAL]], i32 0, i32 0
// NONANS-NEXT:    [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nofpclass(inf) { double, double } @defined_complex_func_f64_ret
// NOINFS-SAME: (double noundef nofpclass(inf) [[C_COERCE0:%.*]], double noundef nofpclass(inf) [[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 nuw { double, double }, ptr [[C]], i32 0, i32 0
// NOINFS-NEXT:    store double [[C_COERCE0]], ptr [[TMP0]], align 8
// NOINFS-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[C]], i32 0, i32 1
// NOINFS-NEXT:    store double [[C_COERCE1]], ptr [[TMP1]], align 8
// NOINFS-NEXT:    [[C_REALP:%.*]] = getelementptr inbounds nuw { 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 nuw { 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 nuw { 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 nuw { 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 ninf nofpclass(inf) { double, double } @__muldc3(double noundef nofpclass(inf) [[C_REAL]], double noundef nofpclass(inf) [[C_IMAG]], double noundef nofpclass(inf) [[C_REAL2]], double noundef nofpclass(inf) [[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 nuw { double, double }, ptr [[RETVAL]], i32 0, i32 0
// NOINFS-NEXT:    [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nofpclass(nan inf) <2 x half> @defined_complex_func_f16_ret
// CFINITEONLY-SAME: (<2 x half> noundef nofpclass(nan inf) [[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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nofpclass(nan inf) <2 x float> @__mulsc3(float noundef nofpclass(nan inf) [[EXT]], float noundef nofpclass(nan inf) [[EXT1]], float noundef nofpclass(nan inf) [[EXT6]], float noundef nofpclass(nan inf) [[EXT7]]) #[[ATTR7]]
// CFINITEONLY-NEXT:    store <2 x float> [[CALL]], ptr [[COERCE]], align 4
// CFINITEONLY-NEXT:    [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { 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 nuw { 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 nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0
// CFINITEONLY-NEXT:    [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nofpclass(nan inf) <2 x half> @defined_complex_func_f16_ret
// CLFINITEONLY-SAME: (<2 x half> noundef nofpclass(nan inf) [[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> poison, 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 nofpclass(nan) <2 x half> @defined_complex_func_f16_ret
// NONANS-SAME: (<2 x half> noundef nofpclass(nan) [[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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nofpclass(nan) <2 x float> @__mulsc3(float noundef nofpclass(nan) [[EXT]], float noundef nofpclass(nan) [[EXT1]], float noundef nofpclass(nan) [[EXT6]], float noundef nofpclass(nan) [[EXT7]]) #[[ATTR7]]
// NONANS-NEXT:    store <2 x float> [[CALL]], ptr [[COERCE]], align 4
// NONANS-NEXT:    [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { 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 nuw { 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 nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0
// NONANS-NEXT:    [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nofpclass(inf) <2 x half> @defined_complex_func_f16_ret
// NOINFS-SAME: (<2 x half> noundef nofpclass(inf) [[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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nofpclass(inf) <2 x float> @__mulsc3(float noundef nofpclass(inf) [[EXT]], float noundef nofpclass(inf) [[EXT1]], float noundef nofpclass(inf) [[EXT6]], float noundef nofpclass(inf) [[EXT7]]) #[[ATTR7]]
// NOINFS-NEXT:    store <2 x float> [[CALL]], ptr [[COERCE]], align 4
// NOINFS-NEXT:    [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { 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 nuw { 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 nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0
// NOINFS-NEXT:    [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nofpclass(nan inf) float @call_variadic
// CFINITEONLY-SAME: (float noundef nofpclass(nan inf) [[F32:%.*]], double noundef nofpclass(nan inf) [[F64:%.*]], half noundef nofpclass(nan inf) [[F16:%.*]], double noundef nofpclass(nan inf) [[V2F32_COERCE:%.*]], <2 x double> noundef nofpclass(nan inf) [[V2F64:%.*]], i32 noundef [[V2F16_COERCE:%.*]], <2 x float> noundef nofpclass(nan inf) [[CF32_COERCE:%.*]], double noundef nofpclass(nan inf) [[CF64_COERCE0:%.*]], double noundef nofpclass(nan inf) [[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:    [[BYVAL_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 nuw { double, double }, ptr [[CF64]], i32 0, i32 0
// CFINITEONLY-NEXT:    store double [[CF64_COERCE0]], ptr [[TMP0]], align 8
// CFINITEONLY-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { float, float }, ptr [[COERCE4]], i32 0, i32 0
// CFINITEONLY-NEXT:    [[COERCE4_IMAGP:%.*]] = getelementptr inbounds nuw { 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:    [[BYVAL_TEMP_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[BYVAL_TEMP]], i32 0, i32 0
// CFINITEONLY-NEXT:    [[BYVAL_TEMP_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[BYVAL_TEMP]], i32 0, i32 1
// CFINITEONLY-NEXT:    store double [[CF64_REAL]], ptr [[BYVAL_TEMP_REALP]], align 8
// CFINITEONLY-NEXT:    store double [[CF64_IMAG]], ptr [[BYVAL_TEMP_IMAGP]], align 8
// CFINITEONLY-NEXT:    [[COERCE5_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[COERCE5]], i32 0, i32 0
// CFINITEONLY-NEXT:    [[COERCE5_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nofpclass(nan inf) float (float, ...) @variadic(float noundef nofpclass(nan inf) [[TMP2]], double noundef nofpclass(nan inf) [[CONV]], double noundef nofpclass(nan inf) [[TMP4]], half noundef nofpclass(nan inf) [[TMP5]], double noundef nofpclass(nan inf) [[TMP9]], <2 x double> noundef nofpclass(nan inf) [[TMP7]], i32 noundef [[TMP10]], <2 x float> noundef nofpclass(nan inf) [[TMP11]], ptr noundef byval({ double, double }) align 8 [[BYVAL_TEMP]], <2 x half> noundef nofpclass(nan inf) [[TMP12]])
// CFINITEONLY-NEXT:    ret float [[CALL]]
//
// CLFINITEONLY: Function Attrs: convergent norecurse nounwind
// CLFINITEONLY-LABEL: define dso_local nofpclass(nan inf) float @call_variadic
// CLFINITEONLY-SAME: (float noundef nofpclass(nan inf) [[F32:%.*]], double noundef nofpclass(nan inf) [[F64:%.*]], half noundef nofpclass(nan inf) [[F16:%.*]], double noundef nofpclass(nan inf) [[V2F32_COERCE:%.*]], <2 x double> noundef nofpclass(nan inf) [[V2F64:%.*]], i32 noundef [[V2F16_COERCE:%.*]], <2 x float> noundef nofpclass(nan inf) [[CF32_COERCE:%.*]], double noundef nofpclass(nan inf) [[CF64_COERCE0:%.*]], double noundef nofpclass(nan inf) [[CF64_COERCE1:%.*]], ptr nocapture noundef readonly byval({ half, half }) align 8 [[CF16:%.*]]) local_unnamed_addr #[[ATTR5]] {
// CLFINITEONLY-NEXT:  entry:
// CLFINITEONLY-NEXT:    [[BYVAL_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 nuw i8, ptr [[CF16]], i64 2
// CLFINITEONLY-NEXT:    [[CF16_IMAG:%.*]] = load half, ptr [[CF16_IMAGP]], align 2
// CLFINITEONLY-NEXT:    call void @llvm.lifetime.start.p0(i64 16, ptr nonnull [[BYVAL_TEMP]]) #[[ATTR12:[0-9]+]]
// CLFINITEONLY-NEXT:    [[BYVAL_TEMP_IMAGP:%.*]] = getelementptr inbounds nuw i8, ptr [[BYVAL_TEMP]], i64 8
// CLFINITEONLY-NEXT:    store double [[CF64_COERCE0]], ptr [[BYVAL_TEMP]], align 8
// CLFINITEONLY-NEXT:    store double [[CF64_COERCE1]], ptr [[BYVAL_TEMP_IMAGP]], align 8
// CLFINITEONLY-NEXT:    [[COERCE5_SROA_0_0_VEC_INSERT:%.*]] = insertelement <2 x half> poison, 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 nofpclass(nan inf) float (float, ...) @variadic(float noundef nofpclass(nan inf) [[F32]], double noundef nofpclass(nan inf) [[CONV]], double noundef nofpclass(nan inf) [[F64]], half noundef nofpclass(nan inf) [[F16]], double noundef nofpclass(nan inf) [[V2F32_COERCE]], <2 x double> noundef nofpclass(nan inf) [[V2F64]], i32 noundef [[V2F16_COERCE]], <2 x float> noundef nofpclass(nan inf) [[CF32_COERCE]], ptr noundef nonnull byval({ double, double }) align 8 [[BYVAL_TEMP]], <2 x half> noundef nofpclass(nan inf) [[COERCE5_SROA_0_2_VEC_INSERT]]) #[[ATTR11]]
// CLFINITEONLY-NEXT:    call void @llvm.lifetime.end.p0(i64 16, ptr nonnull [[BYVAL_TEMP]]) #[[ATTR12]]
// CLFINITEONLY-NEXT:    ret float [[CALL]]
//
// NONANS: Function Attrs: noinline nounwind optnone
// NONANS-LABEL: define dso_local nofpclass(nan) float @call_variadic
// NONANS-SAME: (float noundef nofpclass(nan) [[F32:%.*]], double noundef nofpclass(nan) [[F64:%.*]], half noundef nofpclass(nan) [[F16:%.*]], double noundef nofpclass(nan) [[V2F32_COERCE:%.*]], <2 x double> noundef nofpclass(nan) [[V2F64:%.*]], i32 noundef [[V2F16_COERCE:%.*]], <2 x float> noundef nofpclass(nan) [[CF32_COERCE:%.*]], double noundef nofpclass(nan) [[CF64_COERCE0:%.*]], double noundef nofpclass(nan) [[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:    [[BYVAL_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 nuw { double, double }, ptr [[CF64]], i32 0, i32 0
// NONANS-NEXT:    store double [[CF64_COERCE0]], ptr [[TMP0]], align 8
// NONANS-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { float, float }, ptr [[COERCE4]], i32 0, i32 0
// NONANS-NEXT:    [[COERCE4_IMAGP:%.*]] = getelementptr inbounds nuw { 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:    [[BYVAL_TEMP_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[BYVAL_TEMP]], i32 0, i32 0
// NONANS-NEXT:    [[BYVAL_TEMP_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[BYVAL_TEMP]], i32 0, i32 1
// NONANS-NEXT:    store double [[CF64_REAL]], ptr [[BYVAL_TEMP_REALP]], align 8
// NONANS-NEXT:    store double [[CF64_IMAG]], ptr [[BYVAL_TEMP_IMAGP]], align 8
// NONANS-NEXT:    [[COERCE5_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[COERCE5]], i32 0, i32 0
// NONANS-NEXT:    [[COERCE5_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nofpclass(nan) float (float, ...) @variadic(float noundef nofpclass(nan) [[TMP2]], double noundef nofpclass(nan) [[CONV]], double noundef nofpclass(nan) [[TMP4]], half noundef nofpclass(nan) [[TMP5]], double noundef nofpclass(nan) [[TMP9]], <2 x double> noundef nofpclass(nan) [[TMP7]], i32 noundef [[TMP10]], <2 x float> noundef nofpclass(nan) [[TMP11]], ptr noundef byval({ double, double }) align 8 [[BYVAL_TEMP]], <2 x half> noundef nofpclass(nan) [[TMP12]])
// NONANS-NEXT:    ret float [[CALL]]
//
// NOINFS: Function Attrs: noinline nounwind optnone
// NOINFS-LABEL: define dso_local nofpclass(inf) float @call_variadic
// NOINFS-SAME: (float noundef nofpclass(inf) [[F32:%.*]], double noundef nofpclass(inf) [[F64:%.*]], half noundef nofpclass(inf) [[F16:%.*]], double noundef nofpclass(inf) [[V2F32_COERCE:%.*]], <2 x double> noundef nofpclass(inf) [[V2F64:%.*]], i32 noundef [[V2F16_COERCE:%.*]], <2 x float> noundef nofpclass(inf) [[CF32_COERCE:%.*]], double noundef nofpclass(inf) [[CF64_COERCE0:%.*]], double noundef nofpclass(inf) [[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:    [[BYVAL_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 nuw { double, double }, ptr [[CF64]], i32 0, i32 0
// NOINFS-NEXT:    store double [[CF64_COERCE0]], ptr [[TMP0]], align 8
// NOINFS-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { float, float }, ptr [[COERCE4]], i32 0, i32 0
// NOINFS-NEXT:    [[COERCE4_IMAGP:%.*]] = getelementptr inbounds nuw { 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:    [[BYVAL_TEMP_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[BYVAL_TEMP]], i32 0, i32 0
// NOINFS-NEXT:    [[BYVAL_TEMP_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[BYVAL_TEMP]], i32 0, i32 1
// NOINFS-NEXT:    store double [[CF64_REAL]], ptr [[BYVAL_TEMP_REALP]], align 8
// NOINFS-NEXT:    store double [[CF64_IMAG]], ptr [[BYVAL_TEMP_IMAGP]], align 8
// NOINFS-NEXT:    [[COERCE5_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[COERCE5]], i32 0, i32 0
// NOINFS-NEXT:    [[COERCE5_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nofpclass(inf) float (float, ...) @variadic(float noundef nofpclass(inf) [[TMP2]], double noundef nofpclass(inf) [[CONV]], double noundef nofpclass(inf) [[TMP4]], half noundef nofpclass(inf) [[TMP5]], double noundef nofpclass(inf) [[TMP9]], <2 x double> noundef nofpclass(inf) [[TMP7]], i32 noundef [[TMP10]], <2 x float> noundef nofpclass(inf) [[TMP11]], ptr noundef byval({ double, double }) align 8 [[BYVAL_TEMP]], <2 x half> noundef nofpclass(inf) [[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 nofpclass(nan inf) float @call_variadic_indirect
// CFINITEONLY-SAME: (ptr noundef [[FPTR:%.*]], float noundef nofpclass(nan inf) [[F32:%.*]], double noundef nofpclass(nan inf) [[F64:%.*]], half noundef nofpclass(nan inf) [[F16:%.*]], double noundef nofpclass(nan inf) [[V2F32_COERCE:%.*]], <2 x double> noundef nofpclass(nan inf) [[V2F64:%.*]], i32 noundef [[V2F16_COERCE:%.*]], <2 x float> noundef nofpclass(nan inf) [[CF32_COERCE:%.*]], double noundef nofpclass(nan inf) [[CF64_COERCE0:%.*]], double noundef nofpclass(nan inf) [[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:    [[BYVAL_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 nuw { double, double }, ptr [[CF64]], i32 0, i32 0
// CFINITEONLY-NEXT:    store double [[CF64_COERCE0]], ptr [[TMP0]], align 8
// CFINITEONLY-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { float, float }, ptr [[COERCE4]], i32 0, i32 0
// CFINITEONLY-NEXT:    [[COERCE4_IMAGP:%.*]] = getelementptr inbounds nuw { 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:    [[BYVAL_TEMP_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[BYVAL_TEMP]], i32 0, i32 0
// CFINITEONLY-NEXT:    [[BYVAL_TEMP_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[BYVAL_TEMP]], i32 0, i32 1
// CFINITEONLY-NEXT:    store double [[CF64_REAL]], ptr [[BYVAL_TEMP_REALP]], align 8
// CFINITEONLY-NEXT:    store double [[CF64_IMAG]], ptr [[BYVAL_TEMP_IMAGP]], align 8
// CFINITEONLY-NEXT:    [[COERCE5_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[COERCE5]], i32 0, i32 0
// CFINITEONLY-NEXT:    [[COERCE5_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nofpclass(nan inf) float (float, ...) [[TMP2]](float noundef nofpclass(nan inf) [[TMP3]], double noundef nofpclass(nan inf) [[CONV]], double noundef nofpclass(nan inf) [[TMP5]], half noundef nofpclass(nan inf) [[TMP6]], double noundef nofpclass(nan inf) [[TMP10]], <2 x double> noundef nofpclass(nan inf) [[TMP8]], i32 noundef [[TMP11]], <2 x float> noundef nofpclass(nan inf) [[TMP12]], ptr noundef byval({ double, double }) align 8 [[BYVAL_TEMP]], <2 x half> noundef nofpclass(nan inf) [[TMP13]])
// CFINITEONLY-NEXT:    ret float [[CALL]]
//
// CLFINITEONLY: Function Attrs: convergent norecurse nounwind
// CLFINITEONLY-LABEL: define dso_local nofpclass(nan inf) float @call_variadic_indirect
// CLFINITEONLY-SAME: (ptr nocapture noundef readonly [[FPTR:%.*]], float noundef nofpclass(nan inf) [[F32:%.*]], double noundef nofpclass(nan inf) [[F64:%.*]], half noundef nofpclass(nan inf) [[F16:%.*]], double noundef nofpclass(nan inf) [[V2F32_COERCE:%.*]], <2 x double> noundef nofpclass(nan inf) [[V2F64:%.*]], i32 noundef [[V2F16_COERCE:%.*]], <2 x float> noundef nofpclass(nan inf) [[CF32_COERCE:%.*]], double noundef nofpclass(nan inf) [[CF64_COERCE0:%.*]], double noundef nofpclass(nan inf) [[CF64_COERCE1:%.*]], ptr nocapture noundef readonly byval({ half, half }) align 8 [[CF16:%.*]]) local_unnamed_addr #[[ATTR5]] {
// CLFINITEONLY-NEXT:  entry:
// CLFINITEONLY-NEXT:    [[BYVAL_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 nuw i8, ptr [[CF16]], i64 2
// CLFINITEONLY-NEXT:    [[CF16_IMAG:%.*]] = load half, ptr [[CF16_IMAGP]], align 2
// CLFINITEONLY-NEXT:    call void @llvm.lifetime.start.p0(i64 16, ptr nonnull [[BYVAL_TEMP]]) #[[ATTR12]]
// CLFINITEONLY-NEXT:    [[BYVAL_TEMP_IMAGP:%.*]] = getelementptr inbounds nuw i8, ptr [[BYVAL_TEMP]], i64 8
// CLFINITEONLY-NEXT:    store double [[CF64_COERCE0]], ptr [[BYVAL_TEMP]], align 8
// CLFINITEONLY-NEXT:    store double [[CF64_COERCE1]], ptr [[BYVAL_TEMP_IMAGP]], align 8
// CLFINITEONLY-NEXT:    [[COERCE5_SROA_0_0_VEC_INSERT:%.*]] = insertelement <2 x half> poison, 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 nofpclass(nan inf) float (float, ...) [[FPTR]](float noundef nofpclass(nan inf) [[F32]], double noundef nofpclass(nan inf) [[CONV]], double noundef nofpclass(nan inf) [[F64]], half noundef nofpclass(nan inf) [[F16]], double noundef nofpclass(nan inf) [[V2F32_COERCE]], <2 x double> noundef nofpclass(nan inf) [[V2F64]], i32 noundef [[V2F16_COERCE]], <2 x float> noundef nofpclass(nan inf) [[CF32_COERCE]], ptr noundef nonnull byval({ double, double }) align 8 [[BYVAL_TEMP]], <2 x half> noundef nofpclass(nan inf) [[COERCE5_SROA_0_2_VEC_INSERT]]) #[[ATTR11]]
// CLFINITEONLY-NEXT:    call void @llvm.lifetime.end.p0(i64 16, ptr nonnull [[BYVAL_TEMP]]) #[[ATTR12]]
// CLFINITEONLY-NEXT:    ret float [[CALL]]
//
// NONANS: Function Attrs: noinline nounwind optnone
// NONANS-LABEL: define dso_local nofpclass(nan) float @call_variadic_indirect
// NONANS-SAME: (ptr noundef [[FPTR:%.*]], float noundef nofpclass(nan) [[F32:%.*]], double noundef nofpclass(nan) [[F64:%.*]], half noundef nofpclass(nan) [[F16:%.*]], double noundef nofpclass(nan) [[V2F32_COERCE:%.*]], <2 x double> noundef nofpclass(nan) [[V2F64:%.*]], i32 noundef [[V2F16_COERCE:%.*]], <2 x float> noundef nofpclass(nan) [[CF32_COERCE:%.*]], double noundef nofpclass(nan) [[CF64_COERCE0:%.*]], double noundef nofpclass(nan) [[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:    [[BYVAL_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 nuw { double, double }, ptr [[CF64]], i32 0, i32 0
// NONANS-NEXT:    store double [[CF64_COERCE0]], ptr [[TMP0]], align 8
// NONANS-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { float, float }, ptr [[COERCE4]], i32 0, i32 0
// NONANS-NEXT:    [[COERCE4_IMAGP:%.*]] = getelementptr inbounds nuw { 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:    [[BYVAL_TEMP_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[BYVAL_TEMP]], i32 0, i32 0
// NONANS-NEXT:    [[BYVAL_TEMP_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[BYVAL_TEMP]], i32 0, i32 1
// NONANS-NEXT:    store double [[CF64_REAL]], ptr [[BYVAL_TEMP_REALP]], align 8
// NONANS-NEXT:    store double [[CF64_IMAG]], ptr [[BYVAL_TEMP_IMAGP]], align 8
// NONANS-NEXT:    [[COERCE5_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[COERCE5]], i32 0, i32 0
// NONANS-NEXT:    [[COERCE5_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nofpclass(nan) float (float, ...) [[TMP2]](float noundef nofpclass(nan) [[TMP3]], double noundef nofpclass(nan) [[CONV]], double noundef nofpclass(nan) [[TMP5]], half noundef nofpclass(nan) [[TMP6]], double noundef nofpclass(nan) [[TMP10]], <2 x double> noundef nofpclass(nan) [[TMP8]], i32 noundef [[TMP11]], <2 x float> noundef nofpclass(nan) [[TMP12]], ptr noundef byval({ double, double }) align 8 [[BYVAL_TEMP]], <2 x half> noundef nofpclass(nan) [[TMP13]])
// NONANS-NEXT:    ret float [[CALL]]
//
// NOINFS: Function Attrs: noinline nounwind optnone
// NOINFS-LABEL: define dso_local nofpclass(inf) float @call_variadic_indirect
// NOINFS-SAME: (ptr noundef [[FPTR:%.*]], float noundef nofpclass(inf) [[F32:%.*]], double noundef nofpclass(inf) [[F64:%.*]], half noundef nofpclass(inf) [[F16:%.*]], double noundef nofpclass(inf) [[V2F32_COERCE:%.*]], <2 x double> noundef nofpclass(inf) [[V2F64:%.*]], i32 noundef [[V2F16_COERCE:%.*]], <2 x float> noundef nofpclass(inf) [[CF32_COERCE:%.*]], double noundef nofpclass(inf) [[CF64_COERCE0:%.*]], double noundef nofpclass(inf) [[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:    [[BYVAL_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 nuw { double, double }, ptr [[CF64]], i32 0, i32 0
// NOINFS-NEXT:    store double [[CF64_COERCE0]], ptr [[TMP0]], align 8
// NOINFS-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { 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 nuw { float, float }, ptr [[COERCE4]], i32 0, i32 0
// NOINFS-NEXT:    [[COERCE4_IMAGP:%.*]] = getelementptr inbounds nuw { 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:    [[BYVAL_TEMP_REALP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[BYVAL_TEMP]], i32 0, i32 0
// NOINFS-NEXT:    [[BYVAL_TEMP_IMAGP:%.*]] = getelementptr inbounds nuw { double, double }, ptr [[BYVAL_TEMP]], i32 0, i32 1
// NOINFS-NEXT:    store double [[CF64_REAL]], ptr [[BYVAL_TEMP_REALP]], align 8
// NOINFS-NEXT:    store double [[CF64_IMAG]], ptr [[BYVAL_TEMP_IMAGP]], align 8
// NOINFS-NEXT:    [[COERCE5_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[COERCE5]], i32 0, i32 0
// NOINFS-NEXT:    [[COERCE5_IMAGP:%.*]] = getelementptr inbounds nuw { 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 nofpclass(inf) float (float, ...) [[TMP2]](float noundef nofpclass(inf) [[TMP3]], double noundef nofpclass(inf) [[CONV]], double noundef nofpclass(inf) [[TMP5]], half noundef nofpclass(inf) [[TMP6]], double noundef nofpclass(inf) [[TMP10]], <2 x double> noundef nofpclass(inf) [[TMP8]], i32 noundef [[TMP11]], <2 x float> noundef nofpclass(inf) [[TMP12]], ptr noundef byval({ double, double }) align 8 [[BYVAL_TEMP]], <2 x half> noundef nofpclass(inf) [[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 nofpclass(nan inf) <4 x double> @call_m256d
// CFINITEONLY-SAME: (<4 x double> noundef nofpclass(nan inf) [[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 nofpclass(nan inf) <4 x double> (<4 x double>, ...) @extern_m256d(<4 x double> noundef nofpclass(nan inf) [[TMP0]], <4 x double> noundef nofpclass(nan inf) [[TMP1]])
// CFINITEONLY-NEXT:    ret <4 x double> [[CALL]]
//
// CLFINITEONLY: Function Attrs: convergent norecurse nounwind
// CLFINITEONLY-LABEL: define dso_local nofpclass(nan inf) <4 x double> @call_m256d
// CLFINITEONLY-SAME: (<4 x double> noundef nofpclass(nan inf) [[X:%.*]]) local_unnamed_addr #[[ATTR9:[0-9]+]] {
// CLFINITEONLY-NEXT:  entry:
// CLFINITEONLY-NEXT:    [[CALL:%.*]] = tail call nnan ninf nofpclass(nan inf) <4 x double> (<4 x double>, ...) @extern_m256d(<4 x double> noundef nofpclass(nan inf) [[X]], <4 x double> noundef nofpclass(nan inf) [[X]]) #[[ATTR11]]
// CLFINITEONLY-NEXT:    ret <4 x double> [[CALL]]
//
// NONANS: Function Attrs: noinline nounwind optnone
// NONANS-LABEL: define dso_local nofpclass(nan) <4 x double> @call_m256d
// NONANS-SAME: (<4 x double> noundef nofpclass(nan) [[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 nofpclass(nan) <4 x double> (<4 x double>, ...) @extern_m256d(<4 x double> noundef nofpclass(nan) [[TMP0]], <4 x double> noundef nofpclass(nan) [[TMP1]])
// NONANS-NEXT:    ret <4 x double> [[CALL]]
//
// NOINFS: Function Attrs: noinline nounwind optnone
// NOINFS-LABEL: define dso_local nofpclass(inf) <4 x double> @call_m256d
// NOINFS-SAME: (<4 x double> noundef nofpclass(inf) [[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 nofpclass(inf) <4 x double> (<4 x double>, ...) @extern_m256d(<4 x double> noundef nofpclass(inf) [[TMP0]], <4 x double> noundef nofpclass(inf) [[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 nofpclass(nan inf) <25 x double> @call_matrix
// CFINITEONLY-SAME: (<25 x double> noundef nofpclass(nan inf) [[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 nofpclass(nan inf) <25 x double> @extern_matrix(<25 x double> noundef nofpclass(nan inf) [[TMP0]])
// CFINITEONLY-NEXT:    ret <25 x double> [[CALL]]
//
// CLFINITEONLY: Function Attrs: convergent norecurse nounwind
// CLFINITEONLY-LABEL: define dso_local nofpclass(nan inf) <25 x double> @call_matrix
// CLFINITEONLY-SAME: (<25 x double> noundef nofpclass(nan inf) [[X:%.*]]) local_unnamed_addr #[[ATTR10:[0-9]+]] {
// CLFINITEONLY-NEXT:  entry:
// CLFINITEONLY-NEXT:    [[CALL:%.*]] = tail call nnan ninf nofpclass(nan inf) <25 x double> @extern_matrix(<25 x double> noundef nofpclass(nan inf) [[X]]) #[[ATTR11]]
// CLFINITEONLY-NEXT:    ret <25 x double> [[CALL]]
//
// NONANS: Function Attrs: noinline nounwind optnone
// NONANS-LABEL: define dso_local nofpclass(nan) <25 x double> @call_matrix
// NONANS-SAME: (<25 x double> noundef nofpclass(nan) [[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 nofpclass(nan) <25 x double> @extern_matrix(<25 x double> noundef nofpclass(nan) [[TMP0]])
// NONANS-NEXT:    ret <25 x double> [[CALL]]
//
// NOINFS: Function Attrs: noinline nounwind optnone
// NOINFS-LABEL: define dso_local nofpclass(inf) <25 x double> @call_matrix
// NOINFS-SAME: (<25 x double> noundef nofpclass(inf) [[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 nofpclass(inf) <25 x double> @extern_matrix(<25 x double> noundef nofpclass(inf) [[TMP0]])
// NOINFS-NEXT:    ret <25 x double> [[CALL]]
//
dx5x5_t call_matrix(dx5x5_t x) {
  return extern_matrix(x);
}