-
Notifications
You must be signed in to change notification settings - Fork 14.5k
[C++23] [CLANG] Adding C++23 constexpr math functions: fmin, fmax and frexp. #88978
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 3 commits
3acc848
d7050b5
625028a
319fdd0
da06dba
1793cf0
42d7d4c
9f4d632
efeec9b
e384a05
5f67645
49186b9
cf2814d
1c2912c
d32737e
bd536f5
32b788a
501e39a
0cc61eb
c615b22
5eec2db
299df9a
1507a33
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -3440,9 +3440,10 @@ def Fmod : FPMathTemplate, LibBuiltin<"math.h"> { | |||||||
|
||||||||
def Frexp : FPMathTemplate, LibBuiltin<"math.h"> { | ||||||||
let Spellings = ["frexp"]; | ||||||||
let Attributes = [NoThrow]; | ||||||||
let Attributes = [NoThrow, Constexpr]; | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The For reference: llvm-project/clang/utils/TableGen/ClangBuiltinsEmitter.cpp Lines 225 to 226 in 702198f
We may need a new builtin attribute that expresses @philnik777, thoughts? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This also influences There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
@philnik777, are you envisioning something where
I think the existing For the selectively- There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||||||||
let Prototype = "T(T, int*)"; | ||||||||
let AddBuiltinPrefixedAlias = 1; | ||||||||
zahiraam marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
let OnlyBuiltinPrefixedAliasIsConstexpr = 1; | ||||||||
} | ||||||||
|
||||||||
def Ldexp : FPMathTemplate, LibBuiltin<"math.h"> { | ||||||||
|
@@ -3618,7 +3619,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]; | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment re: making the non-prefixed versions |
||||||||
let Prototype = "T(T, T)"; | ||||||||
let AddBuiltinPrefixedAlias = 1; | ||||||||
let OnlyBuiltinPrefixedAliasIsConstexpr = 1; | ||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2922,7 +2922,7 @@ static bool handleFloatFloatBinOp(EvalInfo &Info, 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 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Info.CCEDiag(E, diag::note_constexpr_float_arithmetic) << LHS.isNaN(); | ||
return Info.noteUndefinedBehavior(); | ||
} | ||
|
@@ -14547,6 +14547,20 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { | |
default: | ||
return false; | ||
|
||
case Builtin::BI__builtin_frexp: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The non- Some more thought is needed on how to handle the non- There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added the non-`_builtin prefixed cases. |
||
case Builtin::BI__builtin_frexpf: | ||
tbaederr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
case Builtin::BI__builtin_frexpl: { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You mean adding : There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
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 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return true; | ||
} | ||
case Builtin::BI__builtin_huge_val: | ||
case Builtin::BI__builtin_huge_valf: | ||
case Builtin::BI__builtin_huge_vall: | ||
|
@@ -14638,6 +14652,9 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { | |
return true; | ||
} | ||
|
||
case Builtin::BIfmin: | ||
case Builtin::BIfminf: | ||
Comment on lines
+15093
to
+15094
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't make these evaluate in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These have to be made
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
Sorry, something went wrong. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we'll be missing at least "pedantic" diagnostics if we don't restrict the The interaction with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At the Clang C/C++ Language Workgroup call on 2024-05-15, it was agreed that For me, the first expectation for this PR (on that subject) is an update to the documentation of @AaronBallman @ldionne, I am no sure how we want to handle this w.r.t. documenting the C++23 implementation status. Does it go in both the Clang documentation (for the functions shared with C) and the libc++ documentation (for the overloads added by C++)? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think anything should happen to the libc++ documentation in this patch. We can update the implementation to behave the same across the different overloads in a follow-up and update our documentation then. |
||
case Builtin::BIfminl: | ||
case Builtin::BI__builtin_fmin: | ||
case Builtin::BI__builtin_fminf: | ||
case Builtin::BI__builtin_fminl: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
#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 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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, &i); | ||
constexpr double f10 = __builtin_frexp(0.0, &i); | ||
constexpr double f11 = __builtin_frexp(-0.0, &i); | ||
constexpr double f12 = __builtin_frexpf(NAN, &i); | ||
constexpr double f13 = __builtin_frexpf(-NAN, &i); | ||
constexpr double f14 = __builtin_frexpf(INFINITY, &i); | ||
hubert-reinterpretcast marked this conversation as resolved.
Show resolved
Hide resolved
|
||
constexpr double f15 = __builtin_frexpf(INFINITY, &i); | ||
hubert-reinterpretcast marked this conversation as resolved.
Show resolved
Hide resolved
|
||
constexpr long double f16 = __builtin_frexpl(259.328L, &i); | ||
|
||
return 0; | ||
} | ||
|
||
// CHECK: store double 1.300000e+00, ptr {{.*}} | ||
// CHECK: store double -0.000000e+00, ptr {{.*}} | ||
// CHECK: store double -0.000000e+00, ptr {{.*}} | ||
// WIN: store float 0xFFF8000000000000, ptr {{.*}} | ||
// LNX: store float 0x7FF8000000000000, ptr {{.*}} | ||
// CHECK: store float -1.000000e+00, ptr {{.*}} | ||
// CHECK: store float 0xFFF0000000000000, ptr {{.*}} | ||
hubert-reinterpretcast marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// CHECK: store double 1.234560e+02, ptr {{.*}} | ||
|
||
// CHECK: store double 0x3FEEDCCCCCCCCCCD, ptr {{.*}} | ||
// CHECK: store double 0.000000e+00, ptr {{.*}} | ||
// CHECK: store double -0.000000e+00, ptr {{.*}} | ||
// CHECK: store double 0xFFF8000000000000, ptr {{.*}} | ||
// WIN: store double 0x7FF8000000000000, ptr {{.*}} | ||
// LNX: store double 0xFFF8000000000000, ptr {{.*}} | ||
// CHECK: store double 0x7FF0000000000000, ptr {{.*}} | ||
// CHECK: store double 0x7FF0000000000000, ptr {{.*}} | ||
// CHECK: store double 5.065000e-01, ptr {{.*}} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Duplicate this run line for For example replace calls using #if __cplusplus <= 202002L
#define CALL_BUILTIN(BASE_NAME, __VA_ARGS__) __builtin_##BASE_NAME(__VA_ARGS__)
#else
#define CALL_BUILTIN(BASE_NAME, __VA_ARGS__) BASE_NAME(__VA_ARGS__)
#endif There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
|
||
// 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 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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, &i) == 0.96445312500000002); | ||
hubert-reinterpretcast marked this conversation as resolved.
Show resolved
Hide resolved
hubert-reinterpretcast marked this conversation as resolved.
Show resolved
Hide resolved
|
||
static_assert(!__builtin_isnan(__builtin_frexp(123.45, &i)), ""); | ||
hubert-reinterpretcast marked this conversation as resolved.
Show resolved
Hide resolved
|
||
static_assert(__builtin_iszero(__builtin_frexp(0.0, &i)), ""); | ||
static_assert(__builtin_iszero(__builtin_frexp(-0.0, &i)), ""); | ||
static_assert(__builtin_isnan(__builtin_frexp(NAN, &i))); | ||
static_assert(__builtin_isnan(__builtin_frexp(-NAN, &i))); | ||
static_assert(!__builtin_isfinite(__builtin_frexp(INFINITY, &i))); | ||
static_assert(!__builtin_isfinite(__builtin_frexp(-INFINITY, &i))); | ||
|
||
return 0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a separate
FrexpF16F128
that should probably also be updated.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have added
UnprefixedOnlyConstexprSince
to the classLIBBUILTIN
so it will be unknow if I add it to this def. I will wait to see if the changes I made were correct and update this rule accordingly.