https://github.com/tex3d created https://github.com/llvm/llvm-project/pull/113636
This change is part of this proposal: https://discourse.llvm.org/t/rfc-all-the-math-intrinsics/78294 - `Builtins.td` - Add f16 support for libm atan2 builtin - `CGBuiltin.cpp` - Emit constraint atan2 intrinsic for clang builtin Part of Implement the atan2 HLSL Function https://github.com/llvm/llvm-project/issues/70096. >From 0c9dfb67a7371b9c4087d7b54e6f93e780038117 Mon Sep 17 00:00:00 2001 From: Tex Riddell <t...@microsoft.com> Date: Tue, 15 Oct 2024 16:18:44 -0700 Subject: [PATCH 1/2] Emit constrained atan2 intrinsic for clang builtin This change is part of this proposal: https://discourse.llvm.org/t/rfc-all-the-math-intrinsics/78294 - `Builtins.td` - Add f16 support for libm atan2 builtin - `CGBuiltin.cpp` - Emit constraint atan2 intrinsic for clang builtin Part of Implement the atan2 HLSL Function #70096. --- clang/include/clang/Basic/Builtins.td | 6 +++--- clang/lib/CodeGen/CGBuiltin.cpp | 11 ++++++++++ clang/test/CodeGen/X86/math-builtins.c | 14 ++++++------- .../test/CodeGen/constrained-math-builtins.c | 7 +++++++ clang/test/CodeGen/libcalls.c | 7 +++---- clang/test/CodeGen/math-libcalls.c | 20 +++++++++---------- .../test/CodeGenCXX/builtin-calling-conv.cpp | 10 +++++----- clang/test/CodeGenOpenCL/builtins-f16.cl | 3 +++ 8 files changed, 49 insertions(+), 29 deletions(-) diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 90475a361bb8f8..0d77f4105bb757 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -227,10 +227,10 @@ def FminimumNumF16F128 : Builtin, F16F128MathTemplate { let Prototype = "T(T, T)"; } -def Atan2F128 : Builtin { - let Spellings = ["__builtin_atan2f128"]; +def Atan2F16F128 : Builtin, F16F128MathTemplate { + let Spellings = ["__builtin_atan2"]; let Attributes = [FunctionWithBuiltinPrefix, NoThrow, ConstIgnoringErrnoAndExceptions]; - let Prototype = "__float128(__float128, __float128)"; + let Prototype = "T(T, T)"; } def CopysignF16 : Builtin { diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index e2d03eff8ab4a0..0bec8f32552110 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -2724,6 +2724,17 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, return RValue::get(emitUnaryMaybeConstrainedFPBuiltin( *this, E, Intrinsic::atan, Intrinsic::experimental_constrained_atan)); + case Builtin::BIatan2: + case Builtin::BIatan2f: + case Builtin::BIatan2l: + case Builtin::BI__builtin_atan2: + case Builtin::BI__builtin_atan2f: + case Builtin::BI__builtin_atan2f16: + case Builtin::BI__builtin_atan2l: + case Builtin::BI__builtin_atan2f128: + return RValue::get(emitBinaryMaybeConstrainedFPBuiltin( + *this, E, Intrinsic::atan2, Intrinsic::experimental_constrained_atan2)); + case Builtin::BIceil: case Builtin::BIceilf: case Builtin::BIceill: diff --git a/clang/test/CodeGen/X86/math-builtins.c b/clang/test/CodeGen/X86/math-builtins.c index 48465df21cca19..bf107437fc63a3 100644 --- a/clang/test/CodeGen/X86/math-builtins.c +++ b/clang/test/CodeGen/X86/math-builtins.c @@ -45,10 +45,10 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) { __builtin_atan2(f,f); __builtin_atan2f(f,f) ; __builtin_atan2l(f, f); __builtin_atan2f128(f,f); -// NO__ERRNO: declare double @atan2(double noundef, double noundef) [[READNONE:#[0-9]+]] -// NO__ERRNO: declare float @atan2f(float noundef, float noundef) [[READNONE]] -// NO__ERRNO: declare x86_fp80 @atan2l(x86_fp80 noundef, x86_fp80 noundef) [[READNONE]] -// NO__ERRNO: declare fp128 @atan2f128(fp128 noundef, fp128 noundef) [[READNONE]] +// NO__ERRNO: declare double @llvm.atan2.f64(double, double) [[READNONE_INTRINSIC:#[0-9]+]] +// NO__ERRNO: declare float @llvm.atan2.f32(float, float) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare x86_fp80 @llvm.atan2.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare fp128 @llvm.atan2.f128(fp128, fp128) [[READNONE_INTRINSIC]] // HAS_ERRNO: declare double @atan2(double noundef, double noundef) [[NOT_READNONE]] // HAS_ERRNO: declare float @atan2f(float noundef, float noundef) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @atan2l(x86_fp80 noundef, x86_fp80 noundef) [[NOT_READNONE]] @@ -56,7 +56,7 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) { __builtin_copysign(f,f); __builtin_copysignf(f,f); __builtin_copysignl(f,f); __builtin_copysignf128(f,f); -// NO__ERRNO: declare double @llvm.copysign.f64(double, double) [[READNONE_INTRINSIC:#[0-9]+]] +// NO__ERRNO: declare double @llvm.copysign.f64(double, double) [[READNONE_INTRINSIC]] // NO__ERRNO: declare float @llvm.copysign.f32(float, float) [[READNONE_INTRINSIC]] // NO__ERRNO: declare x86_fp80 @llvm.copysign.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] // NO__ERRNO: declare fp128 @llvm.copysign.f128(fp128, fp128) [[READNONE_INTRINSIC]] @@ -179,7 +179,7 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) { __builtin_acosh(f); __builtin_acoshf(f); __builtin_acoshl(f); __builtin_acoshf128(f); -// NO__ERRNO: declare double @acosh(double noundef) [[READNONE]] +// NO__ERRNO: declare double @acosh(double noundef) [[READNONE:#[0-9]+]] // NO__ERRNO: declare float @acoshf(float noundef) [[READNONE]] // NO__ERRNO: declare x86_fp80 @acoshl(x86_fp80 noundef) [[READNONE]] // NO__ERRNO: declare fp128 @acoshf128(fp128 noundef) [[READNONE]] @@ -721,10 +721,10 @@ __builtin_trunc(f); __builtin_truncf(f); __builtin_truncl(f); __builtin // HAS_ERRNO: declare fp128 @llvm.trunc.f128(fp128) [[READNONE_INTRINSIC]] }; -// NO__ERRNO: attributes [[READNONE]] = { {{.*}}memory(none){{.*}} } // NO__ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}memory(none){{.*}} } // NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } // NO__ERRNO: attributes [[PURE]] = { {{.*}}memory(read){{.*}} } +// NO__ERRNO: attributes [[READNONE]] = { {{.*}}memory(none){{.*}} } // HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } // HAS_ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}memory(none){{.*}} } diff --git a/clang/test/CodeGen/constrained-math-builtins.c b/clang/test/CodeGen/constrained-math-builtins.c index aa77620b445356..68b9e75283c547 100644 --- a/clang/test/CodeGen/constrained-math-builtins.c +++ b/clang/test/CodeGen/constrained-math-builtins.c @@ -57,6 +57,13 @@ __builtin_atan(f); __builtin_atanf(f); __builtin_atanl(f); __builti // CHECK: call x86_fp80 @llvm.experimental.constrained.atan.f80(x86_fp80 %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict") // CHECK: call fp128 @llvm.experimental.constrained.atan.f128(fp128 %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict") +__builtin_atan2(f,f); __builtin_atan2f(f,f); __builtin_atan2l(f,f); __builtin_atan2f128(f,f); + +// CHECK: call double @llvm.experimental.constrained.atan2.f64(double %{{.*}}, double %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict") +// CHECK: call float @llvm.experimental.constrained.atan2.f32(float %{{.*}}, float %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict") +// CHECK: call x86_fp80 @llvm.experimental.constrained.atan2.f80(x86_fp80 %{{.*}}, x86_fp80 %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict") +// CHECK: call fp128 @llvm.experimental.constrained.atan2.f128(fp128 %{{.*}}, fp128 %{{.*}}, metadata !"round.tonearest", metadata !"fpexcept.strict") + __builtin_ceil(f); __builtin_ceilf(f); __builtin_ceill(f); __builtin_ceilf128(f); // CHECK: call double @llvm.experimental.constrained.ceil.f64(double %{{.*}}, metadata !"fpexcept.strict") diff --git a/clang/test/CodeGen/libcalls.c b/clang/test/CodeGen/libcalls.c index b1637121127c5b..1e4b06e34aaf92 100644 --- a/clang/test/CodeGen/libcalls.c +++ b/clang/test/CodeGen/libcalls.c @@ -95,9 +95,9 @@ void test_builtins(double d, float f, long double ld) { double atan2_ = atan2(d, 2); long double atan2l_ = atan2l(ld, ld); float atan2f_ = atan2f(f, f); -// CHECK-NO: declare double @atan2(double noundef, double noundef) [[NUW_RN:#[0-9]+]] -// CHECK-NO: declare x86_fp80 @atan2l(x86_fp80 noundef, x86_fp80 noundef) [[NUW_RN]] -// CHECK-NO: declare float @atan2f(float noundef, float noundef) [[NUW_RN]] +// CHECK-NO: declare double @llvm.atan2.f64(double, double) [[NUW_RNI]] +// CHECK-NO: declare x86_fp80 @llvm.atan2.f80(x86_fp80, x86_fp80) [[NUW_RNI]] +// CHECK-NO: declare float @llvm.atan2.f32(float, float) [[NUW_RNI]] // CHECK-YES: declare double @atan2(double noundef, double noundef) [[NUW]] // CHECK-YES: declare x86_fp80 @atan2l(x86_fp80 noundef, x86_fp80 noundef) [[NUW]] // CHECK-YES: declare float @atan2f(float noundef, float noundef) [[NUW]] @@ -124,5 +124,4 @@ void test_builtins(double d, float f, long double ld) { } // CHECK-YES: attributes [[NUW]] = { nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+x87" } -// CHECK-NO-DAG: attributes [[NUW_RN]] = { nounwind willreturn memory(none){{.*}} } // CHECK-NO-DAG: attributes [[NUW_RNI]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } diff --git a/clang/test/CodeGen/math-libcalls.c b/clang/test/CodeGen/math-libcalls.c index 2226212eca94ee..bcc61c8f046b43 100644 --- a/clang/test/CodeGen/math-libcalls.c +++ b/clang/test/CodeGen/math-libcalls.c @@ -23,19 +23,19 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) { atan2(f,f); atan2f(f,f) ; atan2l(f, f); - // NO__ERRNO: declare double @atan2(double noundef, double noundef) [[READNONE:#[0-9]+]] - // NO__ERRNO: declare float @atan2f(float noundef, float noundef) [[READNONE]] - // NO__ERRNO: declare x86_fp80 @atan2l(x86_fp80 noundef, x86_fp80 noundef) [[READNONE]] + // NO__ERRNO: declare double @llvm.atan2.f64(double, double) [[READNONE_INTRINSIC:#[0-9]+]] + // NO__ERRNO: declare float @llvm.atan2.f32(float, float) [[READNONE_INTRINSIC]] + // NO__ERRNO: declare x86_fp80 @llvm.atan2.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] // HAS_ERRNO: declare double @atan2(double noundef, double noundef) [[NOT_READNONE]] // HAS_ERRNO: declare float @atan2f(float noundef, float noundef) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @atan2l(x86_fp80 noundef, x86_fp80 noundef) [[NOT_READNONE]] - // HAS_MAYTRAP: declare double @atan2(double noundef, double noundef) [[NOT_READNONE:#[0-9]+]] - // HAS_MAYTRAP: declare float @atan2f(float noundef, float noundef) [[NOT_READNONE]] - // HAS_MAYTRAP: declare x86_fp80 @atan2l(x86_fp80 noundef, x86_fp80 noundef) [[NOT_READNONE]] + // HAS_MAYTRAP: declare double @llvm.experimental.constrained.atan2.f64( + // HAS_MAYTRAP: declare float @llvm.experimental.constrained.atan2.f32( + // HAS_MAYTRAP: declare x86_fp80 @llvm.experimental.constrained.atan2.f80( copysign(f,f); copysignf(f,f);copysignl(f,f); - // NO__ERRNO: declare double @llvm.copysign.f64(double, double) [[READNONE_INTRINSIC:#[0-9]+]] + // NO__ERRNO: declare double @llvm.copysign.f64(double, double) [[READNONE_INTRINSIC]] // NO__ERRNO: declare float @llvm.copysign.f32(float, float) [[READNONE_INTRINSIC]] // NO__ERRNO: declare x86_fp80 @llvm.copysign.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] // HAS_ERRNO: declare double @llvm.copysign.f64(double, double) [[READNONE_INTRINSIC:#[0-9]+]] @@ -65,13 +65,13 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) { // HAS_ERRNO: declare double @frexp(double noundef, ptr noundef) [[NOT_READNONE]] // HAS_ERRNO: declare float @frexpf(float noundef, ptr noundef) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @frexpl(x86_fp80 noundef, ptr noundef) [[NOT_READNONE]] - // HAS_MAYTRAP: declare double @frexp(double noundef, ptr noundef) [[NOT_READNONE]] + // HAS_MAYTRAP: declare double @frexp(double noundef, ptr noundef) [[NOT_READNONE:#[0-9]+]] // HAS_MAYTRAP: declare float @frexpf(float noundef, ptr noundef) [[NOT_READNONE]] // HAS_MAYTRAP: declare x86_fp80 @frexpl(x86_fp80 noundef, ptr noundef) [[NOT_READNONE]] ldexp(f,f); ldexpf(f,f); ldexpl(f,f); - // NO__ERRNO: declare double @ldexp(double noundef, i32 noundef) [[READNONE]] + // NO__ERRNO: declare double @ldexp(double noundef, i32 noundef) [[READNONE:#[0-9]+]] // NO__ERRNO: declare float @ldexpf(float noundef, i32 noundef) [[READNONE]] // NO__ERRNO: declare x86_fp80 @ldexpl(x86_fp80 noundef, i32 noundef) [[READNONE]] // HAS_ERRNO: declare double @ldexp(double noundef, i32 noundef) [[NOT_READNONE]] @@ -719,9 +719,9 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) { // HAS_ERRNO: declare x86_fp80 @llvm.trunc.f80(x86_fp80) [[READNONE_INTRINSIC]] }; -// NO__ERRNO: attributes [[READNONE]] = { {{.*}}memory(none){{.*}} } // NO__ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}memory(none){{.*}} } // NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } +// NO__ERRNO: attributes [[READNONE]] = { {{.*}}memory(none){{.*}} } // NO__ERRNO: attributes [[READONLY]] = { {{.*}}memory(read){{.*}} } // HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } diff --git a/clang/test/CodeGenCXX/builtin-calling-conv.cpp b/clang/test/CodeGenCXX/builtin-calling-conv.cpp index 7020d1e0a24144..6b1c308344e05f 100644 --- a/clang/test/CodeGenCXX/builtin-calling-conv.cpp +++ b/clang/test/CodeGenCXX/builtin-calling-conv.cpp @@ -1,8 +1,8 @@ -// RUN: %clang_cc1 -triple x86_64-linux-pc -DREDECL -emit-llvm %s -o - | FileCheck %s -check-prefix LINUX -// RUN: %clang_cc1 -triple spir-unknown-unknown -DREDECL -DSPIR -emit-llvm %s -o - | FileCheck %s -check-prefix SPIR -// RUN: %clang_cc1 -triple x86_64-linux-pc -emit-llvm %s -o - | FileCheck %s -check-prefix LINUX -// RUN: %clang_cc1 -triple spir-unknown-unknown -DSPIR -emit-llvm %s -o - | FileCheck %s -check-prefix SPIR -// RUN: %clang_cc1 -triple i386-windows-pc -fdefault-calling-conv=stdcall -emit-llvm %s -o - | FileCheck %s -check-prefix WIN32 +// RUN: %clang_cc1 -triple x86_64-linux-pc -DREDECL -emit-llvm -fmath-errno %s -o - | FileCheck %s -check-prefix LINUX +// RUN: %clang_cc1 -triple spir-unknown-unknown -DREDECL -DSPIR -emit-llvm -fmath-errno %s -o - | FileCheck %s -check-prefix SPIR +// RUN: %clang_cc1 -triple x86_64-linux-pc -emit-llvm -fmath-errno %s -o - | FileCheck %s -check-prefix LINUX +// RUN: %clang_cc1 -triple spir-unknown-unknown -DSPIR -emit-llvm -fmath-errno %s -o - | FileCheck %s -check-prefix SPIR +// RUN: %clang_cc1 -triple i386-windows-pc -fdefault-calling-conv=stdcall -emit-llvm -fmath-errno %s -o - | FileCheck %s -check-prefix WIN32 #ifdef REDECL namespace std { diff --git a/clang/test/CodeGenOpenCL/builtins-f16.cl b/clang/test/CodeGenOpenCL/builtins-f16.cl index 8150bc1ac9e2d7..e8b62fe0830cdb 100644 --- a/clang/test/CodeGenOpenCL/builtins-f16.cl +++ b/clang/test/CodeGenOpenCL/builtins-f16.cl @@ -15,6 +15,9 @@ void test_half_builtins(half h0, half h1, half h2, int i0) { // CHECK: call half @llvm.atan.f16(half %h0) res = __builtin_atanf16(h0); + // CHECK: call half @llvm.atan2.f16(half %h0, half %h1) + res = __builtin_atan2f16(h0, h1); + // CHECK: call half @llvm.copysign.f16(half %h0, half %h1) res = __builtin_copysignf16(h0, h1); >From b5a4c777280873e9827bb812b95cad32fbf6b7f4 Mon Sep 17 00:00:00 2001 From: Tex Riddell <t...@microsoft.com> Date: Tue, 15 Oct 2024 19:59:01 -0700 Subject: [PATCH 2/2] Use erff instead of atan2 for builtin calling convention check --- .../test/CodeGenCXX/builtin-calling-conv.cpp | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/clang/test/CodeGenCXX/builtin-calling-conv.cpp b/clang/test/CodeGenCXX/builtin-calling-conv.cpp index 6b1c308344e05f..92d698b43be0ab 100644 --- a/clang/test/CodeGenCXX/builtin-calling-conv.cpp +++ b/clang/test/CodeGenCXX/builtin-calling-conv.cpp @@ -1,8 +1,8 @@ -// RUN: %clang_cc1 -triple x86_64-linux-pc -DREDECL -emit-llvm -fmath-errno %s -o - | FileCheck %s -check-prefix LINUX -// RUN: %clang_cc1 -triple spir-unknown-unknown -DREDECL -DSPIR -emit-llvm -fmath-errno %s -o - | FileCheck %s -check-prefix SPIR -// RUN: %clang_cc1 -triple x86_64-linux-pc -emit-llvm -fmath-errno %s -o - | FileCheck %s -check-prefix LINUX -// RUN: %clang_cc1 -triple spir-unknown-unknown -DSPIR -emit-llvm -fmath-errno %s -o - | FileCheck %s -check-prefix SPIR -// RUN: %clang_cc1 -triple i386-windows-pc -fdefault-calling-conv=stdcall -emit-llvm -fmath-errno %s -o - | FileCheck %s -check-prefix WIN32 +// RUN: %clang_cc1 -triple x86_64-linux-pc -DREDECL -emit-llvm %s -o - | FileCheck %s -check-prefix LINUX +// RUN: %clang_cc1 -triple spir-unknown-unknown -DREDECL -DSPIR -emit-llvm %s -o - | FileCheck %s -check-prefix SPIR +// RUN: %clang_cc1 -triple x86_64-linux-pc -emit-llvm %s -o - | FileCheck %s -check-prefix LINUX +// RUN: %clang_cc1 -triple spir-unknown-unknown -DSPIR -emit-llvm %s -o - | FileCheck %s -check-prefix SPIR +// RUN: %clang_cc1 -triple i386-windows-pc -fdefault-calling-conv=stdcall -emit-llvm %s -o - | FileCheck %s -check-prefix WIN32 #ifdef REDECL namespace std { @@ -13,7 +13,7 @@ using size_t = unsigned long; #endif // SPIR } // namespace std -float __builtin_atan2f(float, float); +float __builtin_erff(float); void *operator new(std::size_t); #endif // REDECL @@ -22,32 +22,32 @@ void foo(); void user() { int i; ::operator new(5); - (void)__builtin_atan2f(1.1, 2.2); + (void)__builtin_erff(1.1); foo(); } // LINUX: define{{.*}} void @_Z4userv() // LINUX: call noalias noundef nonnull ptr @_Znwm -// LINUX: call float @atan2f +// LINUX: call float @erff // LINUX: call void @_Z3foov // LINUX: declare noundef nonnull ptr @_Znwm(i64 noundef) -// LINUX: declare float @atan2f(float noundef, float noundef) +// LINUX: declare float @erff(float noundef) // LINUX: declare void @_Z3foov() // SPIR: define{{.*}} spir_func void @_Z4userv() // SPIR: call spir_func noalias noundef nonnull ptr @_Znwj -// SPIR: call spir_func float @atan2f +// SPIR: call spir_func float @erff // SPIR: call spir_func void @_Z3foov // SPIR: declare spir_func noundef nonnull ptr @_Znwj(i32 noundef) -// SPIR: declare spir_func float @atan2f(float noundef, float noundef) +// SPIR: declare spir_func float @erff(float noundef) // SPIR: declare spir_func void @_Z3foov() // Note: Windows /G options should not change the platform default calling // convention of builtins. // WIN32: define dso_local x86_stdcallcc void @"?user@@YGXXZ"() // WIN32: call noalias noundef nonnull ptr @"??2@YAPAXI@Z" -// WIN32: call float @atan2f +// WIN32: call float @erff // WIN32: call x86_stdcallcc void @"?foo@@YGXXZ" // WIN32: declare dso_local noundef nonnull ptr @"??2@YAPAXI@Z"( -// WIN32: declare dso_local float @atan2f(float noundef, float noundef) +// WIN32: declare dso_local float @erff(float noundef) // WIN32: declare dso_local x86_stdcallcc void @"?foo@@YGXXZ"() _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits