[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
zahiraam wrote: @hubert-reinterpretcast Thanks for the reviews/suggestions. Let me know what you think. https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -14547,6 +14547,20 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { default: return false; + case Builtin::BI__builtin_frexp: + case Builtin::BI__builtin_frexpf: + case Builtin::BI__builtin_frexpl: { +LValue Pointer; +if (!EvaluateFloat(E->getArg(0), Result, Info) || +!EvaluatePointer(E->getArg(1), Pointer, Info)) + return false; +llvm::RoundingMode RM = getActiveRoundingMode(Info, E); +int FrexpExp; +FrexpExp = ilogb(Result); +FrexpExp = FrexpExp == llvm::detail::IEEEFloat::IEK_Zero ? 0 : FrexpExp + 1; +Result = scalbn(Result, -FrexpExp, RM); zahiraam wrote: Added function` StoreExponent`. https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ +// RUN: -DWIN -emit-llvm -o - %s | FileCheck %s --check-prefixes=WIN + +// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ +// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefixes=LNX zahiraam wrote: If you don't think it's too verbose, I have used the `update_cc_test_checks.p`y tool to generate the IR. https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
https://github.com/zahiraam updated https://github.com/llvm/llvm-project/pull/88978 >From 3acc848f4fcc68445dfc849f9c6f8d384d3692af Mon Sep 17 00:00:00 2001 From: Zahira Ammarguellat Date: Tue, 16 Apr 2024 13:09:58 -0700 Subject: [PATCH 1/4] Adding C23 constexpr math functions fmin and frexp. --- clang/include/clang/Basic/Builtins.td | 4 +-- clang/lib/AST/ExprConstant.cpp| 16 - clang/test/CodeGen/constexpr-math.cpp | 51 +++ 3 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 clang/test/CodeGen/constexpr-math.cpp diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 52c0dd52c28b1..a35c77286229f 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -3440,7 +3440,7 @@ def Fmod : FPMathTemplate, LibBuiltin<"math.h"> { def Frexp : FPMathTemplate, LibBuiltin<"math.h"> { let Spellings = ["frexp"]; - let Attributes = [NoThrow]; + let Attributes = [NoThrow, Constexpr]; let Prototype = "T(T, int*)"; let AddBuiltinPrefixedAlias = 1; } @@ -3618,7 +3618,7 @@ def Fmax : FPMathTemplate, LibBuiltin<"math.h"> { def Fmin : FPMathTemplate, LibBuiltin<"math.h"> { let Spellings = ["fmin"]; - let Attributes = [NoThrow, Const]; + let Attributes = [NoThrow, Const, Constexpr]; let Prototype = "T(T, T)"; let AddBuiltinPrefixedAlias = 1; let OnlyBuiltinPrefixedAliasIsConstexpr = 1; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 5a36621dc5cce..506621ac7e9c1 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2922,7 +2922,7 @@ static bool handleFloatFloatBinOp(EvalInfo , const BinaryOperator *E, // If during the evaluation of an expression, the result is not // mathematically defined [...], the behavior is undefined. // FIXME: C++ rules require us to not conform to IEEE 754 here. - if (LHS.isNaN()) { + if (!Info.getLangOpts().CPlusPlus23 && LHS.isNaN()) { Info.CCEDiag(E, diag::note_constexpr_float_arithmetic) << LHS.isNaN(); return Info.noteUndefinedBehavior(); } @@ -14547,6 +14547,18 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { default: return false; + case Builtin::BI__builtin_frexpf: + case Builtin::BI__builtin_frexp: { +LValue Pointer; +if (!EvaluateFloat(E->getArg(0), Result, Info) || +!EvaluatePointer(E->getArg(1), Pointer, Info)) + return false; +llvm::RoundingMode RM = +E->getFPFeaturesInEffect(Info.Ctx.getLangOpts()).getRoundingMode(); +int FrexpExp; +Result = llvm::frexp(Result, FrexpExp, RM); +return true; + } case Builtin::BI__builtin_huge_val: case Builtin::BI__builtin_huge_valf: case Builtin::BI__builtin_huge_vall: @@ -14638,6 +14650,8 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { return true; } + case Builtin::BIfmin: + case Builtin::BIfminf: case Builtin::BI__builtin_fmin: case Builtin::BI__builtin_fminf: case Builtin::BI__builtin_fminl: diff --git a/clang/test/CodeGen/constexpr-math.cpp b/clang/test/CodeGen/constexpr-math.cpp new file mode 100644 index 0..446bf3f4f7a50 --- /dev/null +++ b/clang/test/CodeGen/constexpr-math.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ +// RUN: -emit-llvm -o - %s | FileCheck %s + +// RUN %clang_cc1 -x c++ -triple x86_64-linux-gnu -emit-llvm -o - %s \ +// RUN -std=c++23 + +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) + +//constexpr double frexp ( double num, int* exp ); +//constexpr float foo ( float num, int* exp ); + +int func() +{ + int i; + + // fmin + constexpr double f1 = __builtin_fmin(15.24, 1.3); + constexpr double f2 = __builtin_fmin(-0.0, +0.0); + constexpr double f3 = __builtin_fmin(+0.0, -0.0); + constexpr float f4 = __builtin_fminf(NAN, NAN); + constexpr float f5 = __builtin_fminf(NAN, -1); + constexpr float f6 = __builtin_fminf(-INFINITY, 0); + constexpr float f7 = __builtin_fminf(INFINITY, 0); + + // frexp + constexpr double f8 = __builtin_frexp(123.45, ); + constexpr double f9 = __builtin_frexp(0.0, ); + constexpr double f10 = __builtin_frexp(-0.0, ); + constexpr double f11 = __builtin_frexpf(NAN, ); + constexpr double f12 = __builtin_frexpf(-NAN, ); + constexpr double f13 = __builtin_frexpf(INFINITY, ); + constexpr double f14 = __builtin_frexpf(INFINITY, ); + + return 0; +} + +// CHECK: store double 1.30e+00, ptr {{.*}} +// CHECK: store double -0.00e+00, ptr {{.*}} +// CHECK: store double -0.00e+00, ptr {{.*}} +// CHECK: store float 0xFFF8, ptr {{.*}} +// CHECK: store float -1.00e+00, ptr {{.*}} +// CHECK: store float 0xFFF0, ptr {{.*}} + +// CHECK: store double 0x3FEEDCCD, ptr {{.*}} +// CHECK: store double 0.00e+00, ptr {{.*}} +// CHECK: store double -0.00e+00, ptr {{.*}} +// CHECK: store
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -DWIN -verify -std=c++23 -fsyntax-only %s +// RUN: %clang_cc1 -verify -std=c++23 -fsyntax-only %s + +// expected-no-diagnostics + + +#ifdef WIN +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) +#else +#define NAN (__builtin_nanf("")) +#define INFINITY (__builtin_inff()) +#endif + +int main() { +int i; + +// fmin +static_assert(__builtin_fmin(15.24, 1.3) == 1.3, ""); +static_assert(__builtin_fmin(-0.0, +0.0) == -0.0, ""); +static_assert(__builtin_fmin(+0.0, -0.0) == -0.0, ""); hubert-reinterpretcast wrote: ... also, optional `static_assert` message should be removed if not used in a helpful manner. Example (please apply to other lines too): ```suggestion static_assert(is_same_val<__builtin_fmin(-0.0, +0.0), -0.0>); static_assert(is_same_val<__builtin_fmin(+0.0, -0.0), -0.0>); ``` https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ +// RUN: -DWIN -emit-llvm -o - %s | FileCheck %s --check-prefixes=WIN + +// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ +// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefixes=LNX + +#ifdef WIN +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) +#else +#define NAN (__builtin_nanf("")) +#define INFINITY (__builtin_inff()) +#endif + +int func() +{ + int i; + + // fmin + constexpr double f1 = __builtin_fmin(15.24, 1.3); + constexpr double f2 = __builtin_fmin(-0.0, +0.0); + constexpr double f3 = __builtin_fmin(+0.0, -0.0); + constexpr float f4 = __builtin_fminf(NAN, NAN); + constexpr float f5 = __builtin_fminf(NAN, -1); + constexpr float f6 = __builtin_fminf(-INFINITY, 0); + constexpr float f7 = __builtin_fminf(INFINITY, 0); + constexpr long double f8 = __builtin_fminl(123.456L, 789.012L); + + // frexp + constexpr double f9 = __builtin_frexp(123.45, ); + constexpr double f10 = __builtin_frexp(0.0, ); + constexpr double f11 = __builtin_frexp(-0.0, ); + constexpr double f12 = __builtin_frexpf(NAN, ); + constexpr double f13 = __builtin_frexpf(-NAN, ); + constexpr double f14 = __builtin_frexpf(INFINITY, ); hubert-reinterpretcast wrote: Copy/paste errors? ```suggestion constexpr float f12 = __builtin_frexpf(NAN, ); constexpr float f13 = __builtin_frexpf(-NAN, ); constexpr float f14 = __builtin_frexpf(INFINITY, ); ``` https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ +// RUN: -DWIN -emit-llvm -o - %s | FileCheck %s --check-prefixes=WIN + +// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ +// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefixes=LNX hubert-reinterpretcast wrote: None of the `CHECK` lines were being checked... ```suggestion // RUN: -DWIN -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,WIN // RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ // RUN: -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,LNX ``` https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ +// RUN: -DWIN -emit-llvm -o - %s | FileCheck %s --check-prefixes=WIN + +// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ +// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefixes=LNX + +#ifdef WIN +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) +#else +#define NAN (__builtin_nanf("")) +#define INFINITY (__builtin_inff()) +#endif + +int func() +{ + int i; + + // fmin + constexpr double f1 = __builtin_fmin(15.24, 1.3); + constexpr double f2 = __builtin_fmin(-0.0, +0.0); + constexpr double f3 = __builtin_fmin(+0.0, -0.0); + constexpr float f4 = __builtin_fminf(NAN, NAN); + constexpr float f5 = __builtin_fminf(NAN, -1); + constexpr float f6 = __builtin_fminf(-INFINITY, 0); + constexpr float f7 = __builtin_fminf(INFINITY, 0); + constexpr long double f8 = __builtin_fminl(123.456L, 789.012L); + + // frexp + constexpr double f9 = __builtin_frexp(123.45, ); + constexpr double f10 = __builtin_frexp(0.0, ); + constexpr double f11 = __builtin_frexp(-0.0, ); + constexpr double f12 = __builtin_frexpf(NAN, ); + constexpr double f13 = __builtin_frexpf(-NAN, ); + constexpr double f14 = __builtin_frexpf(INFINITY, ); + constexpr double f15 = __builtin_frexpf(INFINITY, ); + constexpr long double f16 = __builtin_frexpl(259.328L, ); + + return 0; +} + +// CHECK: store double 1.30e+00, ptr {{.*}} +// CHECK: store double -0.00e+00, ptr {{.*}} +// CHECK: store double -0.00e+00, ptr {{.*}} +// WIN: store float 0xFFF8, ptr {{.*}} +// LNX: store float 0x7FF8, ptr {{.*}} +// CHECK: store float -1.00e+00, ptr {{.*}} +// CHECK: store float 0xFFF0, ptr {{.*}} hubert-reinterpretcast wrote: This only checks three of the four `float` values. Maybe the test can use `CHECK-NEXT`, `WIN-NEXT`, etc.? https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -DWIN -verify -std=c++23 -fsyntax-only %s +// RUN: %clang_cc1 -verify -std=c++23 -fsyntax-only %s + +// expected-no-diagnostics + + +#ifdef WIN +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) +#else +#define NAN (__builtin_nanf("")) +#define INFINITY (__builtin_inff()) +#endif + +int main() { +int i; + +// fmin +static_assert(__builtin_fmin(15.24, 1.3) == 1.3, ""); +static_assert(__builtin_fmin(-0.0, +0.0) == -0.0, ""); +static_assert(__builtin_fmin(+0.0, -0.0) == -0.0, ""); +static_assert(__builtin_fminf(NAN, -1) == -1, ""); +static_assert(__builtin_fminf(+INFINITY, 0) == 0, ""); +static_assert(__builtin_isinf(__builtin_fminf(-INFINITY, 0)), ""); +static_assert(__builtin_isnan(__builtin_fminf(NAN,NAN)), ""); + +// frexp +static_assert(__builtin_frexp(123.45, ) == 0.9644531250002); hubert-reinterpretcast wrote: Use `123.45 / 128.` instead of `0.9644531250002`. https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -DWIN -verify -std=c++23 -fsyntax-only %s +// RUN: %clang_cc1 -verify -std=c++23 -fsyntax-only %s + +// expected-no-diagnostics + + +#ifdef WIN +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) +#else +#define NAN (__builtin_nanf("")) +#define INFINITY (__builtin_inff()) +#endif + +int main() { hubert-reinterpretcast wrote: Use identity instead of comparisons/classifications for validation: ```suggestion template constexpr bool is_same_val = false; template constexpr bool is_same_val = true; int main() { ``` https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ +// RUN: -DWIN -emit-llvm -o - %s | FileCheck %s --check-prefixes=WIN + +// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ +// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefixes=LNX + +#ifdef WIN +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) +#else +#define NAN (__builtin_nanf("")) +#define INFINITY (__builtin_inff()) +#endif + +int func() +{ + int i; + + // fmin + constexpr double f1 = __builtin_fmin(15.24, 1.3); + constexpr double f2 = __builtin_fmin(-0.0, +0.0); + constexpr double f3 = __builtin_fmin(+0.0, -0.0); + constexpr float f4 = __builtin_fminf(NAN, NAN); + constexpr float f5 = __builtin_fminf(NAN, -1); + constexpr float f6 = __builtin_fminf(-INFINITY, 0); + constexpr float f7 = __builtin_fminf(INFINITY, 0); + constexpr long double f8 = __builtin_fminl(123.456L, 789.012L); + + // frexp + constexpr double f9 = __builtin_frexp(123.45, ); + constexpr double f10 = __builtin_frexp(0.0, ); + constexpr double f11 = __builtin_frexp(-0.0, ); + constexpr double f12 = __builtin_frexpf(NAN, ); + constexpr double f13 = __builtin_frexpf(-NAN, ); + constexpr double f14 = __builtin_frexpf(INFINITY, ); + constexpr double f15 = __builtin_frexpf(INFINITY, ); hubert-reinterpretcast wrote: Copy/paste errors? ```suggestion constexpr float f15 = __builtin_frexpf(-INFINITY, ); ``` https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -DWIN -verify -std=c++23 -fsyntax-only %s +// RUN: %clang_cc1 -verify -std=c++23 -fsyntax-only %s + +// expected-no-diagnostics + + +#ifdef WIN +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) +#else +#define NAN (__builtin_nanf("")) +#define INFINITY (__builtin_inff()) +#endif + +int main() { +int i; + +// fmin +static_assert(__builtin_fmin(15.24, 1.3) == 1.3, ""); +static_assert(__builtin_fmin(-0.0, +0.0) == -0.0, ""); +static_assert(__builtin_fmin(+0.0, -0.0) == -0.0, ""); +static_assert(__builtin_fminf(NAN, -1) == -1, ""); +static_assert(__builtin_fminf(+INFINITY, 0) == 0, ""); +static_assert(__builtin_isinf(__builtin_fminf(-INFINITY, 0)), ""); +static_assert(__builtin_isnan(__builtin_fminf(NAN,NAN)), ""); + +// frexp +static_assert(__builtin_frexp(123.45, ) == 0.9644531250002); +static_assert(!__builtin_isnan(__builtin_frexp(123.45, )), ""); hubert-reinterpretcast wrote: Why is this necessary? ```suggestion ``` https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -14547,6 +14547,20 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { default: return false; + case Builtin::BI__builtin_frexp: + case Builtin::BI__builtin_frexpf: + case Builtin::BI__builtin_frexpl: { +LValue Pointer; +if (!EvaluateFloat(E->getArg(0), Result, Info) || +!EvaluatePointer(E->getArg(1), Pointer, Info)) + return false; +llvm::RoundingMode RM = getActiveRoundingMode(Info, E); +int FrexpExp; +FrexpExp = ilogb(Result); +FrexpExp = FrexpExp == llvm::detail::IEEEFloat::IEK_Zero ? 0 : FrexpExp + 1; +Result = scalbn(Result, -FrexpExp, RM); hubert-reinterpretcast wrote: This is not an improvement over https://github.com/llvm/llvm-project/blob/d7050b53a75a23024502a9e4f56b385256c4722f/clang/lib/AST/ExprConstant.cpp#L14558 It is still the case that no attempt is made to store the value of `FrexpExp` via `Pointer`. Additionally, (although potentially "better" than the status quo of `llvm::frexp`) this adds yet another place where the calculation for IBM double-double would potentially need special maintenance. See https://github.com/llvm/llvm-project/issues/90287. https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
https://github.com/hubert-reinterpretcast edited https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -DWIN -verify -std=c++23 -fsyntax-only %s +// RUN: %clang_cc1 -verify -std=c++23 -fsyntax-only %s + +// expected-no-diagnostics + + +#ifdef WIN +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) +#else +#define NAN (__builtin_nanf("")) +#define INFINITY (__builtin_inff()) +#endif + +extern "C" void abort() noexcept; +extern "C" int write(int, const void*, unsigned long); + +#define assert(condition) \ + do { \ +if (!(condition)) {\ + write(2, "Assertion failed: ", 18); \ + write(2, #condition, sizeof(#condition) - 1);\ + write(2, "\n", 1); \ + abort(); \ +} \ + } while (false) + +int main() { +int i; + +// fmin +static_assert(__builtin_fmin(15.24, 1.3) == 1.3, ""); +static_assert(__builtin_fmin(-0.0, +0.0) == -0.0, ""); +static_assert(__builtin_fmin(+0.0, -0.0) == -0.0, ""); +assert(__builtin_isnan(__builtin_fminf(NAN,NAN))); +assert(__builtin_isnan(__builtin_fminf(NAN, -1))); +assert(__builtin_isnan(__builtin_fminf(-INFINITY, 0))); +assert(__builtin_iszero(__builtin_fminf(+INFINITY, 0))); + +// frexp +static_assert(__builtin_frexp(123.45, ) == 0.9644531250002); hubert-reinterpretcast wrote: @zahiraam, make `simulateFrexp` a `constexpr` function (maybe with `float` and `long double` overloads as well). ``` template struct FrexpResult { constexpr FrexpResult(T fraction, int exponent) : fraction(fraction), exponent(exponent) {} T fraction; int exponent; friend constexpr bool operator<=>(const FrexpResult &, const FrexpResult &) = default; }; constexpr auto q() { return FrexpResult{0.5, 0}; }; static_assert(q() == FrexpResult{0.5, 0}); ``` https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff a3efc53f168b1451803a40075201c3490d6e3928 625028aed5ad85922f082f5192abd5ceedb0b68d -- clang/test/CodeGenCXX/constexpr-math.cpp clang/test/SemaCXX/constexpr-math.cpp clang/lib/AST/ExprConstant.cpp `` View the diff from clang-format here. ``diff diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 4e66490596..fef6b2fd1d 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -14558,7 +14558,7 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { int FrexpExp; FrexpExp = ilogb(Result); FrexpExp = FrexpExp == llvm::detail::IEEEFloat::IEK_Zero ? 0 : FrexpExp + 1; -Result = scalbn(Result, -FrexpExp, RM); +Result = scalbn(Result, -FrexpExp, RM); return true; } case Builtin::BI__builtin_huge_val: `` https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -DWIN -verify -std=c++23 -fsyntax-only %s +// RUN: %clang_cc1 -verify -std=c++23 -fsyntax-only %s + +// expected-no-diagnostics + + +#ifdef WIN +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) +#else +#define NAN (__builtin_nanf("")) +#define INFINITY (__builtin_inff()) +#endif + +extern "C" void abort() noexcept; +extern "C" int write(int, const void*, unsigned long); + +#define assert(condition) \ + do { \ +if (!(condition)) {\ + write(2, "Assertion failed: ", 18); \ + write(2, #condition, sizeof(#condition) - 1);\ + write(2, "\n", 1); \ + abort(); \ +} \ + } while (false) + +int main() { +int i; + +// fmin +static_assert(__builtin_fmin(15.24, 1.3) == 1.3, ""); +static_assert(__builtin_fmin(-0.0, +0.0) == -0.0, ""); +static_assert(__builtin_fmin(+0.0, -0.0) == -0.0, ""); +assert(__builtin_isnan(__builtin_fminf(NAN,NAN))); +assert(__builtin_isnan(__builtin_fminf(NAN, -1))); +assert(__builtin_isnan(__builtin_fminf(-INFINITY, 0))); +assert(__builtin_iszero(__builtin_fminf(+INFINITY, 0))); + +// frexp +static_assert(__builtin_frexp(123.45, ) == 0.9644531250002); zahiraam wrote: Still working on this. Can you please review the implementation of frexp I have added in `ExprConstant.cpp`? @frederick-vs-ja are you suggesting using something like this for the use of `frexp` in this test? ``` struct FrexpResult { double fraction; int exponent; }; FrexpResult simulateFrexp(double value) { FrexpResult result; result.fraction = __builtin_frexp(value, ); return result; } int main () { double value = 123.456; FrexpResult result = simulateFrexp(123.456); return 0; } ``` Still no way of asserting what the return values of fraction and exponent are from calls to `simulateFrex`p with various arguments. Any suggestions? https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
https://github.com/zahiraam updated https://github.com/llvm/llvm-project/pull/88978 >From 3acc848f4fcc68445dfc849f9c6f8d384d3692af Mon Sep 17 00:00:00 2001 From: Zahira Ammarguellat Date: Tue, 16 Apr 2024 13:09:58 -0700 Subject: [PATCH 1/3] Adding C23 constexpr math functions fmin and frexp. --- clang/include/clang/Basic/Builtins.td | 4 +-- clang/lib/AST/ExprConstant.cpp| 16 - clang/test/CodeGen/constexpr-math.cpp | 51 +++ 3 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 clang/test/CodeGen/constexpr-math.cpp diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 52c0dd52c28b11..a35c77286229ff 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -3440,7 +3440,7 @@ def Fmod : FPMathTemplate, LibBuiltin<"math.h"> { def Frexp : FPMathTemplate, LibBuiltin<"math.h"> { let Spellings = ["frexp"]; - let Attributes = [NoThrow]; + let Attributes = [NoThrow, Constexpr]; let Prototype = "T(T, int*)"; let AddBuiltinPrefixedAlias = 1; } @@ -3618,7 +3618,7 @@ def Fmax : FPMathTemplate, LibBuiltin<"math.h"> { def Fmin : FPMathTemplate, LibBuiltin<"math.h"> { let Spellings = ["fmin"]; - let Attributes = [NoThrow, Const]; + let Attributes = [NoThrow, Const, Constexpr]; let Prototype = "T(T, T)"; let AddBuiltinPrefixedAlias = 1; let OnlyBuiltinPrefixedAliasIsConstexpr = 1; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 5a36621dc5cce2..506621ac7e9c1b 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2922,7 +2922,7 @@ static bool handleFloatFloatBinOp(EvalInfo , const BinaryOperator *E, // If during the evaluation of an expression, the result is not // mathematically defined [...], the behavior is undefined. // FIXME: C++ rules require us to not conform to IEEE 754 here. - if (LHS.isNaN()) { + if (!Info.getLangOpts().CPlusPlus23 && LHS.isNaN()) { Info.CCEDiag(E, diag::note_constexpr_float_arithmetic) << LHS.isNaN(); return Info.noteUndefinedBehavior(); } @@ -14547,6 +14547,18 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { default: return false; + case Builtin::BI__builtin_frexpf: + case Builtin::BI__builtin_frexp: { +LValue Pointer; +if (!EvaluateFloat(E->getArg(0), Result, Info) || +!EvaluatePointer(E->getArg(1), Pointer, Info)) + return false; +llvm::RoundingMode RM = +E->getFPFeaturesInEffect(Info.Ctx.getLangOpts()).getRoundingMode(); +int FrexpExp; +Result = llvm::frexp(Result, FrexpExp, RM); +return true; + } case Builtin::BI__builtin_huge_val: case Builtin::BI__builtin_huge_valf: case Builtin::BI__builtin_huge_vall: @@ -14638,6 +14650,8 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { return true; } + case Builtin::BIfmin: + case Builtin::BIfminf: case Builtin::BI__builtin_fmin: case Builtin::BI__builtin_fminf: case Builtin::BI__builtin_fminl: diff --git a/clang/test/CodeGen/constexpr-math.cpp b/clang/test/CodeGen/constexpr-math.cpp new file mode 100644 index 00..446bf3f4f7a504 --- /dev/null +++ b/clang/test/CodeGen/constexpr-math.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ +// RUN: -emit-llvm -o - %s | FileCheck %s + +// RUN %clang_cc1 -x c++ -triple x86_64-linux-gnu -emit-llvm -o - %s \ +// RUN -std=c++23 + +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) + +//constexpr double frexp ( double num, int* exp ); +//constexpr float foo ( float num, int* exp ); + +int func() +{ + int i; + + // fmin + constexpr double f1 = __builtin_fmin(15.24, 1.3); + constexpr double f2 = __builtin_fmin(-0.0, +0.0); + constexpr double f3 = __builtin_fmin(+0.0, -0.0); + constexpr float f4 = __builtin_fminf(NAN, NAN); + constexpr float f5 = __builtin_fminf(NAN, -1); + constexpr float f6 = __builtin_fminf(-INFINITY, 0); + constexpr float f7 = __builtin_fminf(INFINITY, 0); + + // frexp + constexpr double f8 = __builtin_frexp(123.45, ); + constexpr double f9 = __builtin_frexp(0.0, ); + constexpr double f10 = __builtin_frexp(-0.0, ); + constexpr double f11 = __builtin_frexpf(NAN, ); + constexpr double f12 = __builtin_frexpf(-NAN, ); + constexpr double f13 = __builtin_frexpf(INFINITY, ); + constexpr double f14 = __builtin_frexpf(INFINITY, ); + + return 0; +} + +// CHECK: store double 1.30e+00, ptr {{.*}} +// CHECK: store double -0.00e+00, ptr {{.*}} +// CHECK: store double -0.00e+00, ptr {{.*}} +// CHECK: store float 0xFFF8, ptr {{.*}} +// CHECK: store float -1.00e+00, ptr {{.*}} +// CHECK: store float 0xFFF0, ptr {{.*}} + +// CHECK: store double 0x3FEEDCCD, ptr {{.*}} +// CHECK: store double 0.00e+00, ptr {{.*}} +// CHECK: store double -0.00e+00, ptr {{.*}} +// CHECK:
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -DWIN -verify -std=c++23 -fsyntax-only %s +// RUN: %clang_cc1 -verify -std=c++23 -fsyntax-only %s + +// expected-no-diagnostics + + +#ifdef WIN +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) +#else +#define NAN (__builtin_nanf("")) +#define INFINITY (__builtin_inff()) +#endif + +extern "C" void abort() noexcept; +extern "C" int write(int, const void*, unsigned long); + +#define assert(condition) \ + do { \ +if (!(condition)) {\ + write(2, "Assertion failed: ", 18); \ + write(2, #condition, sizeof(#condition) - 1);\ + write(2, "\n", 1); \ + abort(); \ +} \ + } while (false) + +int main() { +int i; + +// fmin +static_assert(__builtin_fmin(15.24, 1.3) == 1.3, ""); +static_assert(__builtin_fmin(-0.0, +0.0) == -0.0, ""); +static_assert(__builtin_fmin(+0.0, -0.0) == -0.0, ""); +assert(__builtin_isnan(__builtin_fminf(NAN,NAN))); +assert(__builtin_isnan(__builtin_fminf(NAN, -1))); +assert(__builtin_isnan(__builtin_fminf(-INFINITY, 0))); +assert(__builtin_iszero(__builtin_fminf(+INFINITY, 0))); + +// frexp +static_assert(__builtin_frexp(123.45, ) == 0.9644531250002); frederick-vs-ja wrote: It seems that we should write something like ```C++ struct { double num_; int expo_; } result; result.num_ = frexp(x, _); return result; ``` https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
https://github.com/hubert-reinterpretcast edited https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -DWIN -verify -std=c++23 -fsyntax-only %s +// RUN: %clang_cc1 -verify -std=c++23 -fsyntax-only %s + +// expected-no-diagnostics + + +#ifdef WIN +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) +#else +#define NAN (__builtin_nanf("")) +#define INFINITY (__builtin_inff()) +#endif + +extern "C" void abort() noexcept; +extern "C" int write(int, const void*, unsigned long); + +#define assert(condition) \ + do { \ +if (!(condition)) {\ + write(2, "Assertion failed: ", 18); \ + write(2, #condition, sizeof(#condition) - 1);\ + write(2, "\n", 1); \ + abort(); \ +} \ + } while (false) + +int main() { +int i; + +// fmin +static_assert(__builtin_fmin(15.24, 1.3) == 1.3, ""); +static_assert(__builtin_fmin(-0.0, +0.0) == -0.0, ""); +static_assert(__builtin_fmin(+0.0, -0.0) == -0.0, ""); +assert(__builtin_isnan(__builtin_fminf(NAN,NAN))); +assert(__builtin_isnan(__builtin_fminf(NAN, -1))); +assert(__builtin_isnan(__builtin_fminf(-INFINITY, 0))); +assert(__builtin_iszero(__builtin_fminf(+INFINITY, 0))); + +// frexp +static_assert(__builtin_frexp(123.45, ) == 0.9644531250002); hubert-reinterpretcast wrote: Just because a function is `constexpr` does not mean an invocation of it would be allowed in a constant expression even if the arguments were constant expressions. The specific issue is that the semantics of `frexp` has it write a value through it's second parameter. In order to modify the stored value of an object in constant evaluation, the object has to begin its lifetime in that constant evaluation. https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -14638,6 +14649,8 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { return true; } + case Builtin::BIfmin: + case Builtin::BIfminf: hubert-reinterpretcast wrote: I think we'll be missing at least "pedantic" diagnostics if we don't restrict the `constexpr`-ness to C++23 and up. So we do need that restriction. The interaction with `-fno-builtin[-*]` may need more discussion. At least the documentation for that option would need to be updated if the C++23 `constexpr` math would break with it. https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -14638,6 +14649,8 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { return true; } + case Builtin::BIfmin: + case Builtin::BIfminf: hubert-reinterpretcast wrote: > How would that help? I guess it doesn't... The functions would be ambiguous when called... https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
https://github.com/zahiraam edited https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
https://github.com/zahiraam edited https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -DWIN -verify -std=c++23 -fsyntax-only %s +// RUN: %clang_cc1 -verify -std=c++23 -fsyntax-only %s + +// expected-no-diagnostics + + +#ifdef WIN +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) +#else +#define NAN (__builtin_nanf("")) +#define INFINITY (__builtin_inff()) +#endif + +extern "C" void abort() noexcept; +extern "C" int write(int, const void*, unsigned long); + +#define assert(condition) \ + do { \ +if (!(condition)) {\ + write(2, "Assertion failed: ", 18); \ + write(2, #condition, sizeof(#condition) - 1);\ + write(2, "\n", 1); \ + abort(); \ +} \ + } while (false) + +int main() { +int i; + +// fmin +static_assert(__builtin_fmin(15.24, 1.3) == 1.3, ""); +static_assert(__builtin_fmin(-0.0, +0.0) == -0.0, ""); +static_assert(__builtin_fmin(+0.0, -0.0) == -0.0, ""); +assert(__builtin_isnan(__builtin_fminf(NAN,NAN))); +assert(__builtin_isnan(__builtin_fminf(NAN, -1))); +assert(__builtin_isnan(__builtin_fminf(-INFINITY, 0))); +assert(__builtin_iszero(__builtin_fminf(+INFINITY, 0))); + +// frexp +static_assert(__builtin_frexp(123.45, ) == 0.9644531250002); zahiraam wrote: I am reading from `https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0533r9.pdf` that the return type of __builtin_frexp() can be constexpr. This is the result of the code I have added in VisitCallExpr (`case Builtin::BI__builtin_frexpf: case Builtin::BI__builtin_frexp: {} that probably needs to be guarded by getLangOpts().CPlusPlus23). https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -14638,6 +14649,8 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { return true; } + case Builtin::BIfmin: + case Builtin::BIfminf: philnik777 wrote: How would that help? https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -14638,6 +14649,8 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { return true; } + case Builtin::BIfmin: + case Builtin::BIfminf: hubert-reinterpretcast wrote: Makes me wonder how far C++ stdlibs will get if they included the C library headers in an inline namespace under the global namespace (and count on `extern "C"` to handle the linkage names). https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -14638,6 +14649,8 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { return true; } + case Builtin::BIfmin: + case Builtin::BIfminf: philnik777 wrote: These have to be made `constexpr`, at least in C++23. C++ stdlibs can't override them to make them call the `__builtin_` versions, so Clang has to handle that. https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ +// RUN: -DWIN -emit-llvm -o - %s | FileCheck %s --check-prefixes=WIN + +// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ +// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefixes=LNX + +#ifdef WIN +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) +#else +#define NAN (__builtin_nanf("")) +#define INFINITY (__builtin_inff()) +#endif + +int func() +{ + int i; + + // fmin hubert-reinterpretcast wrote: No testing for `long double`? https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -3440,7 +3440,7 @@ def Fmod : FPMathTemplate, LibBuiltin<"math.h"> { def Frexp : FPMathTemplate, LibBuiltin<"math.h"> { let Spellings = ["frexp"]; - let Attributes = [NoThrow]; + let Attributes = [NoThrow, Constexpr]; let Prototype = "T(T, int*)"; let AddBuiltinPrefixedAlias = 1; hubert-reinterpretcast wrote: Should probably match `Fmin` on this: ```suggestion let AddBuiltinPrefixedAlias = 1; let OnlyBuiltinPrefixedAliasIsConstexpr = 1; ``` https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -DWIN -verify -std=c++23 -fsyntax-only %s +// RUN: %clang_cc1 -verify -std=c++23 -fsyntax-only %s + +// expected-no-diagnostics + + +#ifdef WIN +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) +#else +#define NAN (__builtin_nanf("")) +#define INFINITY (__builtin_inff()) +#endif + +extern "C" void abort() noexcept; +extern "C" int write(int, const void*, unsigned long); + +#define assert(condition) \ + do { \ +if (!(condition)) {\ + write(2, "Assertion failed: ", 18); \ + write(2, #condition, sizeof(#condition) - 1);\ + write(2, "\n", 1); \ + abort(); \ +} \ + } while (false) + +int main() { +int i; + +// fmin +static_assert(__builtin_fmin(15.24, 1.3) == 1.3, ""); +static_assert(__builtin_fmin(-0.0, +0.0) == -0.0, ""); +static_assert(__builtin_fmin(+0.0, -0.0) == -0.0, ""); +assert(__builtin_isnan(__builtin_fminf(NAN,NAN))); +assert(__builtin_isnan(__builtin_fminf(NAN, -1))); +assert(__builtin_isnan(__builtin_fminf(-INFINITY, 0))); hubert-reinterpretcast wrote: I doubt the runtime assertions are working (or appropriate in the Clang LIT testing). https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -14638,6 +14649,8 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { return true; } + case Builtin::BIfmin: + case Builtin::BIfminf: hubert-reinterpretcast wrote: Don't make these evaluate in `constexpr`. Not only does this extend C (not a stated intent of the patch), it will cause accidental dependencies that break when `-fno-builtin` is used. https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -14547,6 +14547,17 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { default: return false; + case Builtin::BI__builtin_frexpf: + case Builtin::BI__builtin_frexp: { hubert-reinterpretcast wrote: Why no `long double`? https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
https://github.com/hubert-reinterpretcast requested changes to this pull request. https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -DWIN -verify -std=c++23 -fsyntax-only %s +// RUN: %clang_cc1 -verify -std=c++23 -fsyntax-only %s + +// expected-no-diagnostics + + +#ifdef WIN +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) +#else +#define NAN (__builtin_nanf("")) +#define INFINITY (__builtin_inff()) +#endif + +extern "C" void abort() noexcept; +extern "C" int write(int, const void*, unsigned long); + +#define assert(condition) \ + do { \ +if (!(condition)) {\ + write(2, "Assertion failed: ", 18); \ + write(2, #condition, sizeof(#condition) - 1);\ + write(2, "\n", 1); \ + abort(); \ +} \ + } while (false) + +int main() { +int i; + +// fmin +static_assert(__builtin_fmin(15.24, 1.3) == 1.3, ""); +static_assert(__builtin_fmin(-0.0, +0.0) == -0.0, ""); +static_assert(__builtin_fmin(+0.0, -0.0) == -0.0, ""); +assert(__builtin_isnan(__builtin_fminf(NAN,NAN))); +assert(__builtin_isnan(__builtin_fminf(NAN, -1))); +assert(__builtin_isnan(__builtin_fminf(-INFINITY, 0))); +assert(__builtin_iszero(__builtin_fminf(+INFINITY, 0))); + +// frexp +static_assert(__builtin_frexp(123.45, ) == 0.9644531250002); hubert-reinterpretcast wrote: This should not be a constant expression. This line is not supposed to compile. `i` is supposed to be written to, but it lives outside of the constant expression evaluation. https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -14547,6 +14547,17 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { default: return false; + case Builtin::BI__builtin_frexpf: + case Builtin::BI__builtin_frexp: { +LValue Pointer; +if (!EvaluateFloat(E->getArg(0), Result, Info) || +!EvaluatePointer(E->getArg(1), Pointer, Info)) + return false; +llvm::RoundingMode RM = getActiveRoundingMode(Info, E); +int FrexpExp; +Result = llvm::frexp(Result, FrexpExp, RM); hubert-reinterpretcast wrote: The value in `FrexpExp` is just ignored? https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
https://github.com/hubert-reinterpretcast edited https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -2922,7 +2922,7 @@ static bool handleFloatFloatBinOp(EvalInfo , const BinaryOperator *E, // If during the evaluation of an expression, the result is not // mathematically defined [...], the behavior is undefined. // FIXME: C++ rules require us to not conform to IEEE 754 here. - if (LHS.isNaN()) { + if (!Info.getLangOpts().CPlusPlus23 && LHS.isNaN()) { hubert-reinterpretcast wrote: > Do we want to do the same for C++23? If not what's exactly an "unspecified" > value? It means that `INT_MAX` and `INT_MIN` is fine (based on the wording). The committee discussion had already decided that the constexpr evaluation need not match the target's runtime in terms of implementation-defined behavior with respect to: - what cases are errors, and - how non-error cases of NaNs and infinities, etc. are handled. Instead, C's Annex F was to specify the behaviour; however, that C's Annex F did not fully specify the result (as in the case in question) was not discussed. https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -2922,7 +2922,7 @@ static bool handleFloatFloatBinOp(EvalInfo , const BinaryOperator *E, // If during the evaluation of an expression, the result is not // mathematically defined [...], the behavior is undefined. // FIXME: C++ rules require us to not conform to IEEE 754 here. - if (LHS.isNaN()) { + if (!Info.getLangOpts().CPlusPlus23 && LHS.isNaN()) { zahiraam wrote: > My understanding of the intended design was that operations producing NaNs > from non-NaNs in C++ constexpr cause the expression to not be constant. That > said, NaNs are still in play because of `numeric_limits`. > > For `frexp` though, I think there being an "unspecified" value stored for the > exponent is a problem where the design could use more clarity. I would think > that the operation could still be performed, but the "unspecified" value > should probably be considered indeterminate. For C it looks like it's returning INT_MAX and INT__MIN. See comment/code here: https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/ADT/APFloat.h#L1371 Do we want to do the same for C++23? If not what's exactly an "unspecified" value? https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -2922,7 +2922,7 @@ static bool handleFloatFloatBinOp(EvalInfo , const BinaryOperator *E, // If during the evaluation of an expression, the result is not // mathematically defined [...], the behavior is undefined. // FIXME: C++ rules require us to not conform to IEEE 754 here. - if (LHS.isNaN()) { + if (!Info.getLangOpts().CPlusPlus23 && LHS.isNaN()) { zahiraam wrote: > There's an open CWG issue > ([CWG2168](https://cplusplus.github.io/CWG/issues/2168.html)) about this. That's referring to INFINITY though. This is more specifically about NAN. https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -2922,7 +2922,7 @@ static bool handleFloatFloatBinOp(EvalInfo , const BinaryOperator *E, // If during the evaluation of an expression, the result is not // mathematically defined [...], the behavior is undefined. // FIXME: C++ rules require us to not conform to IEEE 754 here. - if (LHS.isNaN()) { + if (!Info.getLangOpts().CPlusPlus23 && LHS.isNaN()) { frederick-vs-ja wrote: There's an open CWG issue ([CWG2168](https://cplusplus.github.io/CWG/issues/2168.html)) about this. https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -2922,7 +2922,7 @@ static bool handleFloatFloatBinOp(EvalInfo , const BinaryOperator *E, // If during the evaluation of an expression, the result is not // mathematically defined [...], the behavior is undefined. // FIXME: C++ rules require us to not conform to IEEE 754 here. - if (LHS.isNaN()) { + if (!Info.getLangOpts().CPlusPlus23 && LHS.isNaN()) { cor3ntin wrote: > My understanding of the intended design was that operations producing NaNs > from non-NaNs in C++ What is "operation" here? NaN in arithmetics / conversions / other core language etc are one thing, but when calling a function which is specifically specified to produce NaN in some cases... it's very unclear to me that the program should be invalid. If that's the intent, is there anywhere where it would be documented? https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -2922,7 +2922,7 @@ static bool handleFloatFloatBinOp(EvalInfo , const BinaryOperator *E, // If during the evaluation of an expression, the result is not // mathematically defined [...], the behavior is undefined. // FIXME: C++ rules require us to not conform to IEEE 754 here. - if (LHS.isNaN()) { + if (!Info.getLangOpts().CPlusPlus23 && LHS.isNaN()) { hubert-reinterpretcast wrote: My understanding of the intended design was that operations producing NaNs from non-NaNs in C++ constexpr cause the expression to not be constant. That said, NaNs are still in play because of `numeric_limits`. For `frexp` though, I think there being an "unspecified" value stored for the exponent is a problem where the design could use more clarity. I would think that the operation could still be performed, but the "unspecified" value should probably be considered indeterminate. https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
https://github.com/jcranmer-intel commented: Other side notes: fmin and frexp can signal exceptions if the input is an sNaN, which causes [library.c]p3 to kick in. (That's the only time these operations can signal an exception.) https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -2922,7 +2922,7 @@ static bool handleFloatFloatBinOp(EvalInfo , const BinaryOperator *E, // If during the evaluation of an expression, the result is not // mathematically defined [...], the behavior is undefined. // FIXME: C++ rules require us to not conform to IEEE 754 here. - if (LHS.isNaN()) { + if (!Info.getLangOpts().CPlusPlus23 && LHS.isNaN()) { jcranmer-intel wrote: https://eel.is/c++draft/library.c#3 says that >A call to a C standard library function is a non-constant library call >([defns.nonconst.libcall]) if it raises a floating-point exception other than >FE_INEXACT.)" which suggests that floating-point exceptions should generally cause things to fall out of constant expressions. C's Annex F suggests that warnings be emitted for constant expressions that cause floating-point exceptions other than FE_INEXACT (see F.8.2p2). As for wording, [expr.pre]p4 requires that things be "mathematically defined", except IEEE 754 specifically says (in section 3.2) > The mathematical structure underpinning the arithmetic in this standard is > the extended reals, that is, the set of real numbers together with positive and negative infinity. The C++ specification actually does define "mathematically defined" somewhere, in a footnote of https://eel.is/c++draft/sf.cmath.general: > A mathematical function is mathematically defined for a given set of argument > values (a) if it is explicitly defined for that set of argument values, or > (b) if its limiting value exists and does not depend on the direction of > approach. (which, as pendants will note, only defines it for functions, not the base operations of C++, and sidesteps the question of what the set of argument values actually is). It does seem pretty clear from all the standards that a result of infinity is clearly part of the representable types, and it seems a reasonable inference that the result being infinity is "mathematically defined" (division by 0 is permissible in the extended real numbers). The role of NaNs is... clear as mud. You have to go into the definition of to find out that NaN is a representable value. IEEE 754 gives multiple specification levels for floating-point, where NaN is a part of some of them, and proceeds to ignore the fact that it did so in the rest of the specification; the definition of operations involving NaN is deferred into an entire separate section. Section 7.2 goes so far as to say that > The invalid operation exception is signaled if and only if there is no > usefully definable result. In these cases the operands are invalid for the operation to be performed. Is `0.0 / 0.0` "mathematically defined" per IEEE 754? It's definitely *defined*, but I don't think I can entirely endorse saying that it's "mathematically defined." The rule of thumb that FE_INVALID is signaled when the inputs are non-qNaN but the output is NaN, combined with the above text, makes it suspect that it should be considered a "mathematical" definition. But this also doesn't help with `NaN / NaN`, which is `NaN` but doesn't throw a FE_INVALID. As noted in the CWG issue Aaron linked to, someone needs to write a paper to clarify this, and... that's going to be me isn't it? https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -2922,7 +2922,7 @@ static bool handleFloatFloatBinOp(EvalInfo , const BinaryOperator *E, // If during the evaluation of an expression, the result is not // mathematically defined [...], the behavior is undefined. // FIXME: C++ rules require us to not conform to IEEE 754 here. - if (LHS.isNaN()) { + if (!Info.getLangOpts().CPlusPlus23 && LHS.isNaN()) { zahiraam wrote: So, the comment in the code above is not quite correct right? Should that entire condition be removed? https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -2922,7 +2922,7 @@ static bool handleFloatFloatBinOp(EvalInfo , const BinaryOperator *E, // If during the evaluation of an expression, the result is not // mathematically defined [...], the behavior is undefined. // FIXME: C++ rules require us to not conform to IEEE 754 here. - if (LHS.isNaN()) { + if (!Info.getLangOpts().CPlusPlus23 && LHS.isNaN()) { cor3ntin wrote: This is a C function the semantics should reasonably be that of C https://eel.is/c++draft/c.math#cmath.syn-1 fmin is well defined for Nan https://en.cppreference.com/w/c/numeric/math/fmin frexp is well defined for NaN https://en.cppreference.com/w/cpp/numeric/math/frexp https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -2922,7 +2922,7 @@ static bool handleFloatFloatBinOp(EvalInfo , const BinaryOperator *E, // If during the evaluation of an expression, the result is not // mathematically defined [...], the behavior is undefined. // FIXME: C++ rules require us to not conform to IEEE 754 here. - if (LHS.isNaN()) { + if (!Info.getLangOpts().CPlusPlus23 && LHS.isNaN()) { AaronBallman wrote: The plot thickens, this may be a case where it's defined in C but C++ doesn't bother defining much of anything about floating-point and thus it is UB: https://github.com/cplusplus/draft/issues/5407 That said, https://eel.is/c++draft/basic.fundamental#12.sentence-8 seems to make this implementation-defined and it would be reasonable for us to define C++ as following the C semantics in situations where C++ is silent on the behavior. C is more clear on this point. C23 5.2.5.3.3p8: Floating types shall be able to represent signed zeros or an unsigned zero and all normalized floating point numbers. In addition, floating types may be able to contain other kinds of floating-point numbers, such as subnormal floating-point numbers and unnormalized floating-point numbers, and values that are not floating-point numbers, such as NaNs and (signed and unsigned) infinities. https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -2922,7 +2922,7 @@ static bool handleFloatFloatBinOp(EvalInfo , const BinaryOperator *E, // If during the evaluation of an expression, the result is not // mathematically defined [...], the behavior is undefined. // FIXME: C++ rules require us to not conform to IEEE 754 here. - if (LHS.isNaN()) { + if (!Info.getLangOpts().CPlusPlus23 && LHS.isNaN()) { AaronBallman wrote: I think we're potentially misinterpreting the standard here regarding NANs. CC @jcranmer-intel @hubert-reinterpretcast https://eel.is/c++draft/basic.fundamental#13 is the interesting bit (I think), and I believe it's saying that if the floating-point representation you use has a way to represent a mathematical value then that value is "representable in that type". e.g., if your fp format can support positive/negative infinity, then a positive/negative infinity is considered representable. Note 10 says that more explicitly as: "Since negative and positive infinity are representable in ISO/IEC/IEEE 60559 formats, all real numbers lie within the range of representable values of a floating-point type adhering to ISO/IEC/IEEE 60559." NANs are representable within ISO/IEC 60559 and are a mathematical result of an operation such as zero divided by zero. So I believe NANs are valid in a constant expression. MSVC, Clang, and GCC all agree that they're not, but EDG believes they are: https://godbolt.org/z/cxPcKGvP3 https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Zahira Ammarguellat (zahiraam) Changes Add support for for fmin and frexp. --- Full diff: https://github.com/llvm/llvm-project/pull/88978.diff 4 Files Affected: - (modified) clang/include/clang/Basic/Builtins.td (+2-2) - (modified) clang/lib/AST/ExprConstant.cpp (+14-1) - (added) clang/test/CodeGenCXX/constexpr-math.cpp (+55) - (added) clang/test/SemaCXX/constexpr-math.cpp (+57) ``diff diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 52c0dd52c28b11..a35c77286229ff 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -3440,7 +3440,7 @@ def Fmod : FPMathTemplate, LibBuiltin<"math.h"> { def Frexp : FPMathTemplate, LibBuiltin<"math.h"> { let Spellings = ["frexp"]; - let Attributes = [NoThrow]; + let Attributes = [NoThrow, Constexpr]; let Prototype = "T(T, int*)"; let AddBuiltinPrefixedAlias = 1; } @@ -3618,7 +3618,7 @@ def Fmax : FPMathTemplate, LibBuiltin<"math.h"> { def Fmin : FPMathTemplate, LibBuiltin<"math.h"> { let Spellings = ["fmin"]; - let Attributes = [NoThrow, Const]; + let Attributes = [NoThrow, Const, Constexpr]; let Prototype = "T(T, T)"; let AddBuiltinPrefixedAlias = 1; let OnlyBuiltinPrefixedAliasIsConstexpr = 1; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 5a36621dc5cce2..1a6abb386071c7 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2922,7 +2922,7 @@ static bool handleFloatFloatBinOp(EvalInfo , const BinaryOperator *E, // If during the evaluation of an expression, the result is not // mathematically defined [...], the behavior is undefined. // FIXME: C++ rules require us to not conform to IEEE 754 here. - if (LHS.isNaN()) { + if (!Info.getLangOpts().CPlusPlus23 && LHS.isNaN()) { Info.CCEDiag(E, diag::note_constexpr_float_arithmetic) << LHS.isNaN(); return Info.noteUndefinedBehavior(); } @@ -14547,6 +14547,17 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { default: return false; + case Builtin::BI__builtin_frexpf: + case Builtin::BI__builtin_frexp: { +LValue Pointer; +if (!EvaluateFloat(E->getArg(0), Result, Info) || +!EvaluatePointer(E->getArg(1), Pointer, Info)) + return false; +llvm::RoundingMode RM = getActiveRoundingMode(Info, E); +int FrexpExp; +Result = llvm::frexp(Result, FrexpExp, RM); +return true; + } case Builtin::BI__builtin_huge_val: case Builtin::BI__builtin_huge_valf: case Builtin::BI__builtin_huge_vall: @@ -14638,6 +14649,8 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { return true; } + case Builtin::BIfmin: + case Builtin::BIfminf: case Builtin::BI__builtin_fmin: case Builtin::BI__builtin_fminf: case Builtin::BI__builtin_fminl: diff --git a/clang/test/CodeGenCXX/constexpr-math.cpp b/clang/test/CodeGenCXX/constexpr-math.cpp new file mode 100644 index 00..ad7b6779a4ae0e --- /dev/null +++ b/clang/test/CodeGenCXX/constexpr-math.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ +// RUN: -DWIN -emit-llvm -o - %s | FileCheck %s --check-prefixes=WIN + +// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ +// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefixes=LNX + +#ifdef WIN +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) +#else +#define NAN (__builtin_nanf("")) +#define INFINITY (__builtin_inff()) +#endif + +int func() +{ + int i; + + // fmin + constexpr double f1 = __builtin_fmin(15.24, 1.3); + constexpr double f2 = __builtin_fmin(-0.0, +0.0); + constexpr double f3 = __builtin_fmin(+0.0, -0.0); + constexpr float f4 = __builtin_fminf(NAN, NAN); + constexpr float f5 = __builtin_fminf(NAN, -1); + constexpr float f6 = __builtin_fminf(-INFINITY, 0); + constexpr float f7 = __builtin_fminf(INFINITY, 0); + + // frexp + constexpr double f8 = __builtin_frexp(123.45, ); + constexpr double f9 = __builtin_frexp(0.0, ); + constexpr double f10 = __builtin_frexp(-0.0, ); + constexpr double f11 = __builtin_frexpf(NAN, ); + constexpr double f12 = __builtin_frexpf(-NAN, ); + constexpr double f13 = __builtin_frexpf(INFINITY, ); + constexpr double f14 = __builtin_frexpf(INFINITY, ); + + return 0; +} + +// CHECK: store double 1.30e+00, ptr {{.*}} +// CHECK: store double -0.00e+00, ptr {{.*}} +// CHECK: store double -0.00e+00, ptr {{.*}} +// WIN: store float 0xFFF8, ptr {{.*}} +// LNX: store float 0x7FF8, ptr {{.*}} +// CHECK: store float -1.00e+00, ptr {{.*}} +// CHECK: store float 0xFFF0, ptr {{.*}} + +// CHECK: store double 0x3FEEDCCD, ptr {{.*}} +// CHECK: store double 0.00e+00, ptr {{.*}} +// CHECK: store double -0.00e+00, ptr {{.*}} +// CHECK: store double 0xFFF8, ptr
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
https://github.com/zahiraam ready_for_review https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -2922,7 +2922,7 @@ static bool handleFloatFloatBinOp(EvalInfo , const BinaryOperator *E, // If during the evaluation of an expression, the result is not // mathematically defined [...], the behavior is undefined. // FIXME: C++ rules require us to not conform to IEEE 754 here. - if (LHS.isNaN()) { + if (!Info.getLangOpts().CPlusPlus23 && LHS.isNaN()) { zahiraam wrote: This is basically to allow calls of __bultin_func(NAN, NAN) to be legal. https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
https://github.com/zahiraam updated https://github.com/llvm/llvm-project/pull/88978 >From 3acc848f4fcc68445dfc849f9c6f8d384d3692af Mon Sep 17 00:00:00 2001 From: Zahira Ammarguellat Date: Tue, 16 Apr 2024 13:09:58 -0700 Subject: [PATCH 1/2] Adding C23 constexpr math functions fmin and frexp. --- clang/include/clang/Basic/Builtins.td | 4 +-- clang/lib/AST/ExprConstant.cpp| 16 - clang/test/CodeGen/constexpr-math.cpp | 51 +++ 3 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 clang/test/CodeGen/constexpr-math.cpp diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 52c0dd52c28b11..a35c77286229ff 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -3440,7 +3440,7 @@ def Fmod : FPMathTemplate, LibBuiltin<"math.h"> { def Frexp : FPMathTemplate, LibBuiltin<"math.h"> { let Spellings = ["frexp"]; - let Attributes = [NoThrow]; + let Attributes = [NoThrow, Constexpr]; let Prototype = "T(T, int*)"; let AddBuiltinPrefixedAlias = 1; } @@ -3618,7 +3618,7 @@ def Fmax : FPMathTemplate, LibBuiltin<"math.h"> { def Fmin : FPMathTemplate, LibBuiltin<"math.h"> { let Spellings = ["fmin"]; - let Attributes = [NoThrow, Const]; + let Attributes = [NoThrow, Const, Constexpr]; let Prototype = "T(T, T)"; let AddBuiltinPrefixedAlias = 1; let OnlyBuiltinPrefixedAliasIsConstexpr = 1; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 5a36621dc5cce2..506621ac7e9c1b 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2922,7 +2922,7 @@ static bool handleFloatFloatBinOp(EvalInfo , const BinaryOperator *E, // If during the evaluation of an expression, the result is not // mathematically defined [...], the behavior is undefined. // FIXME: C++ rules require us to not conform to IEEE 754 here. - if (LHS.isNaN()) { + if (!Info.getLangOpts().CPlusPlus23 && LHS.isNaN()) { Info.CCEDiag(E, diag::note_constexpr_float_arithmetic) << LHS.isNaN(); return Info.noteUndefinedBehavior(); } @@ -14547,6 +14547,18 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { default: return false; + case Builtin::BI__builtin_frexpf: + case Builtin::BI__builtin_frexp: { +LValue Pointer; +if (!EvaluateFloat(E->getArg(0), Result, Info) || +!EvaluatePointer(E->getArg(1), Pointer, Info)) + return false; +llvm::RoundingMode RM = +E->getFPFeaturesInEffect(Info.Ctx.getLangOpts()).getRoundingMode(); +int FrexpExp; +Result = llvm::frexp(Result, FrexpExp, RM); +return true; + } case Builtin::BI__builtin_huge_val: case Builtin::BI__builtin_huge_valf: case Builtin::BI__builtin_huge_vall: @@ -14638,6 +14650,8 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { return true; } + case Builtin::BIfmin: + case Builtin::BIfminf: case Builtin::BI__builtin_fmin: case Builtin::BI__builtin_fminf: case Builtin::BI__builtin_fminl: diff --git a/clang/test/CodeGen/constexpr-math.cpp b/clang/test/CodeGen/constexpr-math.cpp new file mode 100644 index 00..446bf3f4f7a504 --- /dev/null +++ b/clang/test/CodeGen/constexpr-math.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ +// RUN: -emit-llvm -o - %s | FileCheck %s + +// RUN %clang_cc1 -x c++ -triple x86_64-linux-gnu -emit-llvm -o - %s \ +// RUN -std=c++23 + +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) + +//constexpr double frexp ( double num, int* exp ); +//constexpr float foo ( float num, int* exp ); + +int func() +{ + int i; + + // fmin + constexpr double f1 = __builtin_fmin(15.24, 1.3); + constexpr double f2 = __builtin_fmin(-0.0, +0.0); + constexpr double f3 = __builtin_fmin(+0.0, -0.0); + constexpr float f4 = __builtin_fminf(NAN, NAN); + constexpr float f5 = __builtin_fminf(NAN, -1); + constexpr float f6 = __builtin_fminf(-INFINITY, 0); + constexpr float f7 = __builtin_fminf(INFINITY, 0); + + // frexp + constexpr double f8 = __builtin_frexp(123.45, ); + constexpr double f9 = __builtin_frexp(0.0, ); + constexpr double f10 = __builtin_frexp(-0.0, ); + constexpr double f11 = __builtin_frexpf(NAN, ); + constexpr double f12 = __builtin_frexpf(-NAN, ); + constexpr double f13 = __builtin_frexpf(INFINITY, ); + constexpr double f14 = __builtin_frexpf(INFINITY, ); + + return 0; +} + +// CHECK: store double 1.30e+00, ptr {{.*}} +// CHECK: store double -0.00e+00, ptr {{.*}} +// CHECK: store double -0.00e+00, ptr {{.*}} +// CHECK: store float 0xFFF8, ptr {{.*}} +// CHECK: store float -1.00e+00, ptr {{.*}} +// CHECK: store float 0xFFF0, ptr {{.*}} + +// CHECK: store double 0x3FEEDCCD, ptr {{.*}} +// CHECK: store double 0.00e+00, ptr {{.*}} +// CHECK: store double -0.00e+00, ptr {{.*}} +// CHECK:
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
https://github.com/zahiraam edited https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -2922,7 +2922,7 @@ static bool handleFloatFloatBinOp(EvalInfo , const BinaryOperator *E, // If during the evaluation of an expression, the result is not // mathematically defined [...], the behavior is undefined. // FIXME: C++ rules require us to not conform to IEEE 754 here. - if (LHS.isNaN()) { + if (!Info.getLangOpts().CPlusPlus23 && LHS.isNaN()) { zahiraam wrote: May be additional testing should be added with Linux definition of `NAN`. https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ +// RUN: -emit-llvm -o - %s | FileCheck %s + +// RUN %clang_cc1 -x c++ -triple x86_64-linux-gnu -emit-llvm -o - %s \ +// RUN -std=c++23 + +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) + +//constexpr double frexp ( double num, int* exp ); +//constexpr float foo ( float num, int* exp ); + +int func() +{ + int i; + + // fmin + constexpr double f1 = __builtin_fmin(15.24, 1.3); + constexpr double f2 = __builtin_fmin(-0.0, +0.0); + constexpr double f3 = __builtin_fmin(+0.0, -0.0); + constexpr float f4 = __builtin_fminf(NAN, NAN); + constexpr float f5 = __builtin_fminf(NAN, -1); + constexpr float f6 = __builtin_fminf(-INFINITY, 0); + constexpr float f7 = __builtin_fminf(INFINITY, 0); + + // frexp + constexpr double f8 = __builtin_frexp(123.45, ); + constexpr double f9 = __builtin_frexp(0.0, ); + constexpr double f10 = __builtin_frexp(-0.0, ); + constexpr double f11 = __builtin_frexpf(NAN, ); + constexpr double f12 = __builtin_frexpf(-NAN, ); + constexpr double f13 = __builtin_frexpf(INFINITY, ); + constexpr double f14 = __builtin_frexpf(INFINITY, ); + + return 0; +} zahiraam wrote: Right. The value of `i` is not added. Shoult it be added? https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -2922,7 +2922,7 @@ static bool handleFloatFloatBinOp(EvalInfo , const BinaryOperator *E, // If during the evaluation of an expression, the result is not // mathematically defined [...], the behavior is undefined. // FIXME: C++ rules require us to not conform to IEEE 754 here. - if (LHS.isNaN()) { + if (!Info.getLangOpts().CPlusPlus23 && LHS.isNaN()) { zahiraam wrote: Not sure. We land here when the constexpr builtin_* is using a `NAN` argument with a Windows definition which is: `#define INFINITY ((float)(1e+300 * 1e+300))` `#define NAN (-(float)(INFINITY * 0.0F))` and an` EvalMode= EM_ConstantExpression`. `float f1 = __builtin_fminf(NAN, NAN);` returns an `EvaluateFloat() = true` (`EvalMode= EM_IgnoreSideEffects`) `constexpr float f1 = __builtin_fminf(NAN, NAN);` returns an `EvaluateFloat() = false` (` EvalMode= EM_ConstantExpression`). May be this is not the right place to do that? Should `keepEvaluatingAfterUndefinedBehavior` return true for C++23 when `EvalMode= EM_ConstantExpression`? https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -2922,7 +2922,7 @@ static bool handleFloatFloatBinOp(EvalInfo , const BinaryOperator *E, // If during the evaluation of an expression, the result is not // mathematically defined [...], the behavior is undefined. // FIXME: C++ rules require us to not conform to IEEE 754 here. - if (LHS.isNaN()) { + if (!Info.getLangOpts().CPlusPlus23 && LHS.isNaN()) { tbaederr wrote: Why this change? Is there a part of the standard we should quote in the comment above? https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -14547,6 +14547,18 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { default: return false; + case Builtin::BI__builtin_frexpf: + case Builtin::BI__builtin_frexp: { +LValue Pointer; +if (!EvaluateFloat(E->getArg(0), Result, Info) || +!EvaluatePointer(E->getArg(1), Pointer, Info)) + return false; +llvm::RoundingMode RM = +E->getFPFeaturesInEffect(Info.Ctx.getLangOpts()).getRoundingMode(); tbaederr wrote: `getActiveRoundingMode()`? https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ +// RUN: -emit-llvm -o - %s | FileCheck %s + +// RUN %clang_cc1 -x c++ -triple x86_64-linux-gnu -emit-llvm -o - %s \ +// RUN -std=c++23 + +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) + +//constexpr double frexp ( double num, int* exp ); +//constexpr float foo ( float num, int* exp ); + +int func() +{ + int i; + + // fmin + constexpr double f1 = __builtin_fmin(15.24, 1.3); + constexpr double f2 = __builtin_fmin(-0.0, +0.0); + constexpr double f3 = __builtin_fmin(+0.0, -0.0); + constexpr float f4 = __builtin_fminf(NAN, NAN); + constexpr float f5 = __builtin_fminf(NAN, -1); + constexpr float f6 = __builtin_fminf(-INFINITY, 0); + constexpr float f7 = __builtin_fminf(INFINITY, 0); + + // frexp + constexpr double f8 = __builtin_frexp(123.45, ); + constexpr double f9 = __builtin_frexp(0.0, ); + constexpr double f10 = __builtin_frexp(-0.0, ); + constexpr double f11 = __builtin_frexpf(NAN, ); + constexpr double f12 = __builtin_frexpf(-NAN, ); + constexpr double f13 = __builtin_frexpf(INFINITY, ); + constexpr double f14 = __builtin_frexpf(INFINITY, ); + + return 0; +} tbaederr wrote: These all don't test the value of `i`, right? https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
@@ -14547,6 +14547,18 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { default: return false; + case Builtin::BI__builtin_frexpf: tbaederr wrote: Not doing that is fine for now. https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
https://github.com/zahiraam edited https://github.com/llvm/llvm-project/pull/88978 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits