[clang] [C++23] [CLANG] Adding C++23 constexpr math functions: fmin and frexp. (PR #88978)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 22 13:35:35 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Zahira Ammarguellat (zahiraam)
<details>
<summary>Changes</summary>
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 &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()) {
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 00000000000000..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, &i);
+ constexpr double f9 = __builtin_frexp(0.0, &i);
+ constexpr double f10 = __builtin_frexp(-0.0, &i);
+ constexpr double f11 = __builtin_frexpf(NAN, &i);
+ constexpr double f12 = __builtin_frexpf(-NAN, &i);
+ constexpr double f13 = __builtin_frexpf(INFINITY, &i);
+ constexpr double f14 = __builtin_frexpf(INFINITY, &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 {{.*}}
+
+// 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 {{.*}}
diff --git a/clang/test/SemaCXX/constexpr-math.cpp b/clang/test/SemaCXX/constexpr-math.cpp
new file mode 100644
index 00000000000000..f51ea1bcaf7bad
--- /dev/null
+++ b/clang/test/SemaCXX/constexpr-math.cpp
@@ -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, &i) == 0.96445312500000002);
+ static_assert(!__builtin_isnan(__builtin_frexp(123.45, &i)), "");
+ assert(i==0);
+ static_assert(__builtin_iszero(__builtin_frexp(0.0, &i)), "");
+ assert(i==0);
+ static_assert(__builtin_iszero(__builtin_frexp(-0.0, &i)), "");
+ assert(i==0);
+ assert(__builtin_isnan(__builtin_frexp(NAN, &i)));
+ assert(i==0);
+ assert(__builtin_isnan(__builtin_frexp(-NAN, &i)));
+ assert(i==0);
+ assert(!__builtin_isfinite(__builtin_frexp(INFINITY, &i)));
+ assert(i==0);
+ assert(!__builtin_isfinite(__builtin_frexp(-INFINITY, &i)));
+ assert(i==0);
+ return 0;
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/88978
More information about the cfe-commits
mailing list