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