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 <zahira.ammarguel...@intel.com> Date: Tue, 16 Apr 2024 13:09:58 -0700 Subject: [PATCH 1/8] 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 &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,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 0000000000000..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, &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 {{.*}} +// CHECK: store float 0xFFF8000000000000, 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 {{.*}} +// CHECK: store double 0x7FF8000000000000, ptr {{.*}} +// CHECK: store double 0x7FF0000000000000, ptr {{.*}} +// CHECK: store double 0x7FF0000000000000, ptr {{.*}} >From d7050b53a75a23024502a9e4f56b385256c4722f Mon Sep 17 00:00:00 2001 From: Zahira Ammarguellat <zahira.ammarguel...@intel.com> Date: Mon, 22 Apr 2024 13:32:56 -0700 Subject: [PATCH 2/8] Addressed review comments. --- clang/lib/AST/ExprConstant.cpp | 3 +- .../constexpr-math.cpp | 20 ++++--- clang/test/SemaCXX/constexpr-math.cpp | 57 +++++++++++++++++++ 3 files changed, 70 insertions(+), 10 deletions(-) rename clang/test/{CodeGen => CodeGenCXX}/constexpr-math.cpp (75%) create mode 100644 clang/test/SemaCXX/constexpr-math.cpp diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 506621ac7e9c1..1a6abb386071c 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -14553,8 +14553,7 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { if (!EvaluateFloat(E->getArg(0), Result, Info) || !EvaluatePointer(E->getArg(1), Pointer, Info)) return false; - llvm::RoundingMode RM = - E->getFPFeaturesInEffect(Info.Ctx.getLangOpts()).getRoundingMode(); + llvm::RoundingMode RM = getActiveRoundingMode(Info, E); int FrexpExp; Result = llvm::frexp(Result, FrexpExp, RM); return true; diff --git a/clang/test/CodeGen/constexpr-math.cpp b/clang/test/CodeGenCXX/constexpr-math.cpp similarity index 75% rename from clang/test/CodeGen/constexpr-math.cpp rename to clang/test/CodeGenCXX/constexpr-math.cpp index 446bf3f4f7a50..ad7b6779a4ae0 100644 --- a/clang/test/CodeGen/constexpr-math.cpp +++ b/clang/test/CodeGenCXX/constexpr-math.cpp @@ -1,14 +1,16 @@ // RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ -// RUN: -emit-llvm -o - %s | FileCheck %s +// RUN: -DWIN -emit-llvm -o - %s | FileCheck %s --check-prefixes=WIN -// RUN %clang_cc1 -x c++ -triple x86_64-linux-gnu -emit-llvm -o - %s \ -// RUN -std=c++23 +// 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)) - -//constexpr double frexp ( double num, int* exp ); -//constexpr float foo ( float num, int* exp ); +#else +#define NAN (__builtin_nanf("")) +#define INFINITY (__builtin_inff()) +#endif int func() { @@ -38,7 +40,8 @@ int func() // CHECK: store double 1.300000e+00, ptr {{.*}} // CHECK: store double -0.000000e+00, ptr {{.*}} // CHECK: store double -0.000000e+00, ptr {{.*}} -// CHECK: store float 0xFFF8000000000000, ptr {{.*}} +// WIN: store float 0xFFF8000000000000, ptr {{.*}} +// LNX: store float 0x7FF8000000000000, ptr {{.*}} // CHECK: store float -1.000000e+00, ptr {{.*}} // CHECK: store float 0xFFF0000000000000, ptr {{.*}} @@ -46,6 +49,7 @@ int func() // CHECK: store double 0.000000e+00, ptr {{.*}} // CHECK: store double -0.000000e+00, ptr {{.*}} // CHECK: store double 0xFFF8000000000000, ptr {{.*}} -// CHECK: store double 0x7FF8000000000000, 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 0000000000000..f51ea1bcaf7ba --- /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; +} >From 625028aed5ad85922f082f5192abd5ceedb0b68d Mon Sep 17 00:00:00 2001 From: Zahira Ammarguellat <zahira.ammarguel...@intel.com> Date: Wed, 1 May 2024 08:44:50 -0700 Subject: [PATCH 3/8] Responded to review comments. --- clang/include/clang/Basic/Builtins.td | 1 + clang/lib/AST/ExprConstant.cpp | 8 +++-- clang/test/CodeGenCXX/constexpr-math.cpp | 16 ++++++---- clang/test/SemaCXX/constexpr-math.cpp | 37 ++++++------------------ 4 files changed, 26 insertions(+), 36 deletions(-) diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index a35c77286229f..419e623c7bc04 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -3443,6 +3443,7 @@ def Frexp : FPMathTemplate, LibBuiltin<"math.h"> { let Attributes = [NoThrow, Constexpr]; let Prototype = "T(T, int*)"; let AddBuiltinPrefixedAlias = 1; + let OnlyBuiltinPrefixedAliasIsConstexpr = 1; } def Ldexp : FPMathTemplate, LibBuiltin<"math.h"> { diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 1a6abb386071c..4e664905969ee 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -14547,15 +14547,18 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { default: return false; + case Builtin::BI__builtin_frexp: case Builtin::BI__builtin_frexpf: - case Builtin::BI__builtin_frexp: { + 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; - Result = llvm::frexp(Result, FrexpExp, RM); + FrexpExp = ilogb(Result); + FrexpExp = FrexpExp == llvm::detail::IEEEFloat::IEK_Zero ? 0 : FrexpExp + 1; + Result = scalbn(Result, -FrexpExp, RM); return true; } case Builtin::BI__builtin_huge_val: @@ -14651,6 +14654,7 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BIfmin: case Builtin::BIfminf: + case Builtin::BIfminl: 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 index ad7b6779a4ae0..a48c312d05af0 100644 --- a/clang/test/CodeGenCXX/constexpr-math.cpp +++ b/clang/test/CodeGenCXX/constexpr-math.cpp @@ -24,15 +24,17 @@ int func() 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 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 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); + constexpr double f15 = __builtin_frexpf(INFINITY, &i); + constexpr long double f16 = __builtin_frexpl(259.328L, &i); return 0; } @@ -44,6 +46,7 @@ int func() // LNX: store float 0x7FF8000000000000, ptr {{.*}} // CHECK: store float -1.000000e+00, ptr {{.*}} // CHECK: store float 0xFFF0000000000000, ptr {{.*}} +// CHECK: store double 1.234560e+02, ptr {{.*}} // CHECK: store double 0x3FEEDCCCCCCCCCCD, ptr {{.*}} // CHECK: store double 0.000000e+00, ptr {{.*}} @@ -53,3 +56,4 @@ int func() // LNX: store double 0xFFF8000000000000, ptr {{.*}} // CHECK: store double 0x7FF0000000000000, ptr {{.*}} // CHECK: store double 0x7FF0000000000000, ptr {{.*}} +// CHECK: store double 5.065000e-01, ptr {{.*}} diff --git a/clang/test/SemaCXX/constexpr-math.cpp b/clang/test/SemaCXX/constexpr-math.cpp index f51ea1bcaf7ba..24e5bf70e3535 100644 --- a/clang/test/SemaCXX/constexpr-math.cpp +++ b/clang/test/SemaCXX/constexpr-math.cpp @@ -12,19 +12,6 @@ #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; @@ -32,26 +19,20 @@ int main() { 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))); + 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); 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); + 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; } >From 319fdd0867bdd9e7a9decfba8dc2f1be6e375a19 Mon Sep 17 00:00:00 2001 From: Zahira Ammarguellat <zahira.ammarguel...@intel.com> Date: Wed, 8 May 2024 10:27:54 -0700 Subject: [PATCH 4/8] Added code to store the exponent in Pointer. Edited LIT tests as requested by reviewer. --- clang/lib/AST/ExprConstant.cpp | 22 ++++- clang/test/CodeGenCXX/constexpr-math.cpp | 105 ++++++++++++++++++----- clang/test/SemaCXX/constexpr-math.cpp | 42 ++++----- 3 files changed, 123 insertions(+), 46 deletions(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 4e664905969ee..be68ef11efb38 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -14481,6 +14481,8 @@ class FloatExprEvaluator return true; } + void StoreExponent(LValue Pointer, int exp); + bool VisitCallExpr(const CallExpr *E); bool VisitUnaryOperator(const UnaryOperator *E); @@ -14539,6 +14541,19 @@ static bool TryEvaluateBuiltinNaN(const ASTContext &Context, return true; } +void FloatExprEvaluator::StoreExponent(LValue Pointer, int exp) { + const APValue::LValueBase Base = Pointer.getLValueBase(); + auto *VD = const_cast<ValueDecl *>(Base.dyn_cast<const ValueDecl *>()); + if (auto *VarD = dyn_cast<VarDecl>(VD)) { + clang::IntegerLiteral *IL = + clang::IntegerLiteral::Create(Info.Ctx, llvm::APSInt(32, exp), + Info.Ctx.IntTy, clang::SourceLocation()); + VarD->setInit(IL); + } else { + llvm_unreachable("expecting a VarDecl for an exponent"); + } +} + bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { if (!IsConstantEvaluatedBuiltinCall(E)) return ExprEvaluatorBaseTy::VisitCallExpr(E); @@ -14554,11 +14569,10 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { 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); + llvm::RoundingMode RM = getActiveRoundingMode(Info, E); + Result = llvm::frexp(Result, FrexpExp, RM); + StoreExponent(Pointer, FrexpExp); return true; } case Builtin::BI__builtin_huge_val: diff --git a/clang/test/CodeGenCXX/constexpr-math.cpp b/clang/test/CodeGenCXX/constexpr-math.cpp index a48c312d05af0..039d2f288ddfa 100644 --- a/clang/test/CodeGenCXX/constexpr-math.cpp +++ b/clang/test/CodeGenCXX/constexpr-math.cpp @@ -1,3 +1,4 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 // RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ // RUN: -DWIN -emit-llvm -o - %s | FileCheck %s --check-prefixes=WIN @@ -12,6 +13,84 @@ #define INFINITY (__builtin_inff()) #endif +// WIN-LABEL: define dso_local noundef i32 @_Z4funcv( +// WIN-SAME: ) #[[ATTR0:[0-9]+]] { +// WIN-NEXT: entry: +// WIN-NEXT: [[I:%.*]] = alloca i32, align 4 +// WIN-NEXT: [[F1:%.*]] = alloca double, align 8 +// WIN-NEXT: [[F2:%.*]] = alloca double, align 8 +// WIN-NEXT: [[F3:%.*]] = alloca double, align 8 +// WIN-NEXT: [[F4:%.*]] = alloca float, align 4 +// WIN-NEXT: [[F5:%.*]] = alloca float, align 4 +// WIN-NEXT: [[F6:%.*]] = alloca float, align 4 +// WIN-NEXT: [[F7:%.*]] = alloca float, align 4 +// WIN-NEXT: [[F8:%.*]] = alloca x86_fp80, align 16 +// WIN-NEXT: [[F9:%.*]] = alloca double, align 8 +// WIN-NEXT: [[F10:%.*]] = alloca double, align 8 +// WIN-NEXT: [[F11:%.*]] = alloca double, align 8 +// WIN-NEXT: [[F12:%.*]] = alloca float, align 4 +// WIN-NEXT: [[F13:%.*]] = alloca float, align 4 +// WIN-NEXT: [[F14:%.*]] = alloca float, align 4 +// WIN-NEXT: [[F15:%.*]] = alloca float, align 4 +// WIN-NEXT: [[F16:%.*]] = alloca x86_fp80, align 16 +// WIN-NEXT: store i32 0, ptr [[I]], align 4 +// WIN-NEXT: store double 1.300000e+00, ptr [[F1]], align 8 +// WIN-NEXT: store double -0.000000e+00, ptr [[F2]], align 8 +// WIN-NEXT: store double -0.000000e+00, ptr [[F3]], align 8 +// WIN-NEXT: store float 0xFFF8000000000000, ptr [[F4]], align 4 +// WIN-NEXT: store float -1.000000e+00, ptr [[F5]], align 4 +// WIN-NEXT: store float 0xFFF0000000000000, ptr [[F6]], align 4 +// WIN-NEXT: store float 0.000000e+00, ptr [[F7]], align 4 +// WIN-NEXT: store x86_fp80 0xK4005F6E978D4FDF3B646, ptr [[F8]], align 16 +// WIN-NEXT: store double 0x3FEEDCCCCCCCCCCD, ptr [[F9]], align 8 +// WIN-NEXT: store double 0.000000e+00, ptr [[F10]], align 8 +// WIN-NEXT: store double -0.000000e+00, ptr [[F11]], align 8 +// WIN-NEXT: store float 0xFFF8000000000000, ptr [[F12]], align 4 +// WIN-NEXT: store float 0x7FF8000000000000, ptr [[F13]], align 4 +// WIN-NEXT: store float 0x7FF0000000000000, ptr [[F14]], align 4 +// WIN-NEXT: store float 0x7FF0000000000000, ptr [[F15]], align 4 +// WIN-NEXT: store x86_fp80 0xK3FFE81A9FBE76C8B4396, ptr [[F16]], align 16 +// WIN-NEXT: ret i32 0 +// +// LNX-LABEL: define dso_local noundef i32 @_Z4funcv( +// LNX-SAME: ) #[[ATTR0:[0-9]+]] { +// LNX-NEXT: entry: +// LNX-NEXT: [[I:%.*]] = alloca i32, align 4 +// LNX-NEXT: [[F1:%.*]] = alloca double, align 8 +// LNX-NEXT: [[F2:%.*]] = alloca double, align 8 +// LNX-NEXT: [[F3:%.*]] = alloca double, align 8 +// LNX-NEXT: [[F4:%.*]] = alloca float, align 4 +// LNX-NEXT: [[F5:%.*]] = alloca float, align 4 +// LNX-NEXT: [[F6:%.*]] = alloca float, align 4 +// LNX-NEXT: [[F7:%.*]] = alloca float, align 4 +// LNX-NEXT: [[F8:%.*]] = alloca x86_fp80, align 16 +// LNX-NEXT: [[F9:%.*]] = alloca double, align 8 +// LNX-NEXT: [[F10:%.*]] = alloca double, align 8 +// LNX-NEXT: [[F11:%.*]] = alloca double, align 8 +// LNX-NEXT: [[F12:%.*]] = alloca float, align 4 +// LNX-NEXT: [[F13:%.*]] = alloca float, align 4 +// LNX-NEXT: [[F14:%.*]] = alloca float, align 4 +// LNX-NEXT: [[F15:%.*]] = alloca float, align 4 +// LNX-NEXT: [[F16:%.*]] = alloca x86_fp80, align 16 +// LNX-NEXT: store i32 0, ptr [[I]], align 4 +// LNX-NEXT: store double 1.300000e+00, ptr [[F1]], align 8 +// LNX-NEXT: store double -0.000000e+00, ptr [[F2]], align 8 +// LNX-NEXT: store double -0.000000e+00, ptr [[F3]], align 8 +// LNX-NEXT: store float 0x7FF8000000000000, ptr [[F4]], align 4 +// LNX-NEXT: store float -1.000000e+00, ptr [[F5]], align 4 +// LNX-NEXT: store float 0xFFF0000000000000, ptr [[F6]], align 4 +// LNX-NEXT: store float 0.000000e+00, ptr [[F7]], align 4 +// LNX-NEXT: store x86_fp80 0xK4005F6E978D4FDF3B646, ptr [[F8]], align 16 +// LNX-NEXT: store double 0x3FEEDCCCCCCCCCCD, ptr [[F9]], align 8 +// LNX-NEXT: store double 0.000000e+00, ptr [[F10]], align 8 +// LNX-NEXT: store double -0.000000e+00, ptr [[F11]], align 8 +// LNX-NEXT: store float 0x7FF8000000000000, ptr [[F12]], align 4 +// LNX-NEXT: store float 0xFFF8000000000000, ptr [[F13]], align 4 +// LNX-NEXT: store float 0x7FF0000000000000, ptr [[F14]], align 4 +// LNX-NEXT: store float 0x7FF0000000000000, ptr [[F15]], align 4 +// LNX-NEXT: store x86_fp80 0xK3FFE81A9FBE76C8B4396, ptr [[F16]], align 16 +// LNX-NEXT: ret i32 0 +// int func() { int i; @@ -30,30 +109,12 @@ int func() 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); - constexpr double f15 = __builtin_frexpf(INFINITY, &i); + constexpr float f12 = __builtin_frexpf(NAN, &i); + constexpr float f13 = __builtin_frexpf(-NAN, &i); + constexpr float f14 = __builtin_frexpf(INFINITY, &i); + constexpr float f15 = __builtin_frexpf(INFINITY, &i); 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 {{.*}} -// 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 {{.*}} diff --git a/clang/test/SemaCXX/constexpr-math.cpp b/clang/test/SemaCXX/constexpr-math.cpp index 24e5bf70e3535..2c4c29c1c6542 100644 --- a/clang/test/SemaCXX/constexpr-math.cpp +++ b/clang/test/SemaCXX/constexpr-math.cpp @@ -12,27 +12,29 @@ #define INFINITY (__builtin_inff()) #endif -int main() { - int i; +template <auto, auto> constexpr bool is_same_val = false; +template <auto X> constexpr bool is_same_val<X, X> = true; - // 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)), ""); +int main() { + int i; - // frexp - static_assert(__builtin_frexp(123.45, &i) == 0.96445312500000002); - static_assert(!__builtin_isnan(__builtin_frexp(123.45, &i)), ""); - 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))); + // fmin + static_assert(is_same_val<__builtin_fmin(15.24, 1.3), 1.3>); + 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>); + static_assert(is_same_val<__builtin_fminf(NAN, -1), -1.f>); + static_assert(is_same_val<__builtin_fminf(+INFINITY, 0), 0.f>); + static_assert(is_same_val<__builtin_fminf(-INFINITY, 0), -INFINITY>); + static_assert(is_same_val<__builtin_fminf(NAN, NAN), NAN>); - return 0; + // frexp + static_assert(is_same_val<__builtin_frexp(123.45, &i), 123.45/128>); + static_assert(is_same_val<__builtin_frexp(0.0, &i), 0.0>); + static_assert(is_same_val<__builtin_frexp(-0.0, &i), -0.0>); + static_assert(is_same_val<__builtin_frexpf(NAN, &i), NAN>); + static_assert(is_same_val<__builtin_frexpf(-NAN, &i), -NAN>); + static_assert(is_same_val<__builtin_frexpf(INFINITY, &i), INFINITY>); + static_assert(is_same_val<__builtin_frexpf(-INFINITY, &i), -INFINITY>); + + return 0; } >From da06dba0e58d1d6b29fe91d85104eb285bd311df Mon Sep 17 00:00:00 2001 From: Zahira Ammarguellat <zahira.ammarguel...@intel.com> Date: Thu, 9 May 2024 12:02:00 -0700 Subject: [PATCH 5/8] Added fmax function and function IsinRange function. --- clang/include/clang/Basic/Builtins.td | 2 +- clang/lib/AST/ExprConstant.cpp | 6 + clang/test/CodeGenCXX/constexpr-math.cpp | 202 ++++++++++++++--------- clang/test/SemaCXX/constexpr-math.cpp | 14 +- llvm/include/llvm/ADT/APFloat.h | 13 ++ 5 files changed, 155 insertions(+), 82 deletions(-) diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 419e623c7bc04..75a26e3cf2b58 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -3611,7 +3611,7 @@ def Fma : FPMathTemplate, LibBuiltin<"math.h"> { def Fmax : FPMathTemplate, LibBuiltin<"math.h"> { let Spellings = ["fmax"]; - 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 be68ef11efb38..3a4abab8fd336 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -14572,6 +14572,9 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { int FrexpExp; llvm::RoundingMode RM = getActiveRoundingMode(Info, E); Result = llvm::frexp(Result, FrexpExp, RM); + if (!Result.isZero() && !Result.isNaN() && !Result.isInfinity()) + assert(llvm::APFloat::isInRange(Result) && + "The value is not in the expected range for frexp."); StoreExponent(Pointer, FrexpExp); return true; } @@ -14648,6 +14651,9 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { return true; } + case Builtin::BIfmax: + case Builtin::BIfmaxf: + case Builtin::BIfmaxl: case Builtin::BI__builtin_fmax: case Builtin::BI__builtin_fmaxf: case Builtin::BI__builtin_fmaxl: diff --git a/clang/test/CodeGenCXX/constexpr-math.cpp b/clang/test/CodeGenCXX/constexpr-math.cpp index 039d2f288ddfa..f5546c0fcfed9 100644 --- a/clang/test/CodeGenCXX/constexpr-math.cpp +++ b/clang/test/CodeGenCXX/constexpr-math.cpp @@ -17,78 +17,110 @@ // WIN-SAME: ) #[[ATTR0:[0-9]+]] { // WIN-NEXT: entry: // WIN-NEXT: [[I:%.*]] = alloca i32, align 4 -// WIN-NEXT: [[F1:%.*]] = alloca double, align 8 -// WIN-NEXT: [[F2:%.*]] = alloca double, align 8 -// WIN-NEXT: [[F3:%.*]] = alloca double, align 8 -// WIN-NEXT: [[F4:%.*]] = alloca float, align 4 -// WIN-NEXT: [[F5:%.*]] = alloca float, align 4 -// WIN-NEXT: [[F6:%.*]] = alloca float, align 4 -// WIN-NEXT: [[F7:%.*]] = alloca float, align 4 -// WIN-NEXT: [[F8:%.*]] = alloca x86_fp80, align 16 -// WIN-NEXT: [[F9:%.*]] = alloca double, align 8 -// WIN-NEXT: [[F10:%.*]] = alloca double, align 8 -// WIN-NEXT: [[F11:%.*]] = alloca double, align 8 -// WIN-NEXT: [[F12:%.*]] = alloca float, align 4 -// WIN-NEXT: [[F13:%.*]] = alloca float, align 4 -// WIN-NEXT: [[F14:%.*]] = alloca float, align 4 -// WIN-NEXT: [[F15:%.*]] = alloca float, align 4 -// WIN-NEXT: [[F16:%.*]] = alloca x86_fp80, align 16 +// WIN-NEXT: [[MIN1:%.*]] = alloca double, align 8 +// WIN-NEXT: [[MIN2:%.*]] = alloca double, align 8 +// WIN-NEXT: [[MIN3:%.*]] = alloca double, align 8 +// WIN-NEXT: [[MIN4:%.*]] = alloca float, align 4 +// WIN-NEXT: [[MIN5:%.*]] = alloca float, align 4 +// WIN-NEXT: [[MIN6:%.*]] = alloca float, align 4 +// WIN-NEXT: [[MIN7:%.*]] = alloca float, align 4 +// WIN-NEXT: [[MIN8:%.*]] = alloca x86_fp80, align 16 +// WIN-NEXT: [[MAX1:%.*]] = alloca double, align 8 +// WIN-NEXT: [[MAX2:%.*]] = alloca double, align 8 +// WIN-NEXT: [[MAX3:%.*]] = alloca double, align 8 +// WIN-NEXT: [[MAX4:%.*]] = alloca float, align 4 +// WIN-NEXT: [[MAX5:%.*]] = alloca float, align 4 +// WIN-NEXT: [[MAX6:%.*]] = alloca float, align 4 +// WIN-NEXT: [[MAX7:%.*]] = alloca float, align 4 +// WIN-NEXT: [[MAX8:%.*]] = alloca x86_fp80, align 16 +// WIN-NEXT: [[FREXP1:%.*]] = alloca double, align 8 +// WIN-NEXT: [[FREXP2:%.*]] = alloca double, align 8 +// WIN-NEXT: [[FREXP3:%.*]] = alloca double, align 8 +// WIN-NEXT: [[FREXP4:%.*]] = alloca float, align 4 +// WIN-NEXT: [[FREXP5:%.*]] = alloca float, align 4 +// WIN-NEXT: [[FREXP6:%.*]] = alloca float, align 4 +// WIN-NEXT: [[FREXP7:%.*]] = alloca float, align 4 +// WIN-NEXT: [[FREXP8:%.*]] = alloca x86_fp80, align 16 // WIN-NEXT: store i32 0, ptr [[I]], align 4 -// WIN-NEXT: store double 1.300000e+00, ptr [[F1]], align 8 -// WIN-NEXT: store double -0.000000e+00, ptr [[F2]], align 8 -// WIN-NEXT: store double -0.000000e+00, ptr [[F3]], align 8 -// WIN-NEXT: store float 0xFFF8000000000000, ptr [[F4]], align 4 -// WIN-NEXT: store float -1.000000e+00, ptr [[F5]], align 4 -// WIN-NEXT: store float 0xFFF0000000000000, ptr [[F6]], align 4 -// WIN-NEXT: store float 0.000000e+00, ptr [[F7]], align 4 -// WIN-NEXT: store x86_fp80 0xK4005F6E978D4FDF3B646, ptr [[F8]], align 16 -// WIN-NEXT: store double 0x3FEEDCCCCCCCCCCD, ptr [[F9]], align 8 -// WIN-NEXT: store double 0.000000e+00, ptr [[F10]], align 8 -// WIN-NEXT: store double -0.000000e+00, ptr [[F11]], align 8 -// WIN-NEXT: store float 0xFFF8000000000000, ptr [[F12]], align 4 -// WIN-NEXT: store float 0x7FF8000000000000, ptr [[F13]], align 4 -// WIN-NEXT: store float 0x7FF0000000000000, ptr [[F14]], align 4 -// WIN-NEXT: store float 0x7FF0000000000000, ptr [[F15]], align 4 -// WIN-NEXT: store x86_fp80 0xK3FFE81A9FBE76C8B4396, ptr [[F16]], align 16 +// WIN-NEXT: store double 1.300000e+00, ptr [[MIN1]], align 8 +// WIN-NEXT: store double -0.000000e+00, ptr [[MIN2]], align 8 +// WIN-NEXT: store double -0.000000e+00, ptr [[MIN3]], align 8 +// WIN-NEXT: store float 0xFFF8000000000000, ptr [[MIN4]], align 4 +// WIN-NEXT: store float -1.000000e+00, ptr [[MIN5]], align 4 +// WIN-NEXT: store float 0xFFF0000000000000, ptr [[MIN6]], align 4 +// WIN-NEXT: store float 0.000000e+00, ptr [[MIN7]], align 4 +// WIN-NEXT: store x86_fp80 0xK4005F6E978D4FDF3B646, ptr [[MIN8]], align 16 +// WIN-NEXT: store double 1.524000e+01, ptr [[MAX1]], align 8 +// WIN-NEXT: store double 0.000000e+00, ptr [[MAX2]], align 8 +// WIN-NEXT: store double 0.000000e+00, ptr [[MAX3]], align 8 +// WIN-NEXT: store float -1.000000e+00, ptr [[MAX4]], align 4 +// WIN-NEXT: store float 0x7FF0000000000000, ptr [[MAX5]], align 4 +// WIN-NEXT: store float 0.000000e+00, ptr [[MAX6]], align 4 +// WIN-NEXT: store float 0xFFF8000000000000, ptr [[MAX7]], align 4 +// WIN-NEXT: store x86_fp80 0xK4008C540C49BA5E353F8, ptr [[MAX8]], align 16 +// WIN-NEXT: store double 0x3FEEDCCCCCCCCCCD, ptr [[FREXP1]], align 8 +// WIN-NEXT: store double 0.000000e+00, ptr [[FREXP2]], align 8 +// WIN-NEXT: store double -0.000000e+00, ptr [[FREXP3]], align 8 +// WIN-NEXT: store float 0xFFF8000000000000, ptr [[FREXP4]], align 4 +// WIN-NEXT: store float 0x7FF8000000000000, ptr [[FREXP5]], align 4 +// WIN-NEXT: store float 0x7FF0000000000000, ptr [[FREXP6]], align 4 +// WIN-NEXT: store float 0x7FF0000000000000, ptr [[FREXP7]], align 4 +// WIN-NEXT: store x86_fp80 0xK3FFE81A9FBE76C8B4396, ptr [[FREXP8]], align 16 // WIN-NEXT: ret i32 0 // // LNX-LABEL: define dso_local noundef i32 @_Z4funcv( // LNX-SAME: ) #[[ATTR0:[0-9]+]] { // LNX-NEXT: entry: // LNX-NEXT: [[I:%.*]] = alloca i32, align 4 -// LNX-NEXT: [[F1:%.*]] = alloca double, align 8 -// LNX-NEXT: [[F2:%.*]] = alloca double, align 8 -// LNX-NEXT: [[F3:%.*]] = alloca double, align 8 -// LNX-NEXT: [[F4:%.*]] = alloca float, align 4 -// LNX-NEXT: [[F5:%.*]] = alloca float, align 4 -// LNX-NEXT: [[F6:%.*]] = alloca float, align 4 -// LNX-NEXT: [[F7:%.*]] = alloca float, align 4 -// LNX-NEXT: [[F8:%.*]] = alloca x86_fp80, align 16 -// LNX-NEXT: [[F9:%.*]] = alloca double, align 8 -// LNX-NEXT: [[F10:%.*]] = alloca double, align 8 -// LNX-NEXT: [[F11:%.*]] = alloca double, align 8 -// LNX-NEXT: [[F12:%.*]] = alloca float, align 4 -// LNX-NEXT: [[F13:%.*]] = alloca float, align 4 -// LNX-NEXT: [[F14:%.*]] = alloca float, align 4 -// LNX-NEXT: [[F15:%.*]] = alloca float, align 4 -// LNX-NEXT: [[F16:%.*]] = alloca x86_fp80, align 16 +// LNX-NEXT: [[MIN1:%.*]] = alloca double, align 8 +// LNX-NEXT: [[MIN2:%.*]] = alloca double, align 8 +// LNX-NEXT: [[MIN3:%.*]] = alloca double, align 8 +// LNX-NEXT: [[MIN4:%.*]] = alloca float, align 4 +// LNX-NEXT: [[MIN5:%.*]] = alloca float, align 4 +// LNX-NEXT: [[MIN6:%.*]] = alloca float, align 4 +// LNX-NEXT: [[MIN7:%.*]] = alloca float, align 4 +// LNX-NEXT: [[MIN8:%.*]] = alloca x86_fp80, align 16 +// LNX-NEXT: [[MAX1:%.*]] = alloca double, align 8 +// LNX-NEXT: [[MAX2:%.*]] = alloca double, align 8 +// LNX-NEXT: [[MAX3:%.*]] = alloca double, align 8 +// LNX-NEXT: [[MAX4:%.*]] = alloca float, align 4 +// LNX-NEXT: [[MAX5:%.*]] = alloca float, align 4 +// LNX-NEXT: [[MAX6:%.*]] = alloca float, align 4 +// LNX-NEXT: [[MAX7:%.*]] = alloca float, align 4 +// LNX-NEXT: [[MAX8:%.*]] = alloca x86_fp80, align 16 +// LNX-NEXT: [[FREXP1:%.*]] = alloca double, align 8 +// LNX-NEXT: [[FREXP2:%.*]] = alloca double, align 8 +// LNX-NEXT: [[FREXP3:%.*]] = alloca double, align 8 +// LNX-NEXT: [[FREXP4:%.*]] = alloca float, align 4 +// LNX-NEXT: [[FREXP5:%.*]] = alloca float, align 4 +// LNX-NEXT: [[FREXP6:%.*]] = alloca float, align 4 +// LNX-NEXT: [[FREXP7:%.*]] = alloca float, align 4 +// LNX-NEXT: [[FREXP8:%.*]] = alloca x86_fp80, align 16 // LNX-NEXT: store i32 0, ptr [[I]], align 4 -// LNX-NEXT: store double 1.300000e+00, ptr [[F1]], align 8 -// LNX-NEXT: store double -0.000000e+00, ptr [[F2]], align 8 -// LNX-NEXT: store double -0.000000e+00, ptr [[F3]], align 8 -// LNX-NEXT: store float 0x7FF8000000000000, ptr [[F4]], align 4 -// LNX-NEXT: store float -1.000000e+00, ptr [[F5]], align 4 -// LNX-NEXT: store float 0xFFF0000000000000, ptr [[F6]], align 4 -// LNX-NEXT: store float 0.000000e+00, ptr [[F7]], align 4 -// LNX-NEXT: store x86_fp80 0xK4005F6E978D4FDF3B646, ptr [[F8]], align 16 -// LNX-NEXT: store double 0x3FEEDCCCCCCCCCCD, ptr [[F9]], align 8 -// LNX-NEXT: store double 0.000000e+00, ptr [[F10]], align 8 -// LNX-NEXT: store double -0.000000e+00, ptr [[F11]], align 8 -// LNX-NEXT: store float 0x7FF8000000000000, ptr [[F12]], align 4 -// LNX-NEXT: store float 0xFFF8000000000000, ptr [[F13]], align 4 -// LNX-NEXT: store float 0x7FF0000000000000, ptr [[F14]], align 4 -// LNX-NEXT: store float 0x7FF0000000000000, ptr [[F15]], align 4 -// LNX-NEXT: store x86_fp80 0xK3FFE81A9FBE76C8B4396, ptr [[F16]], align 16 +// LNX-NEXT: store double 1.300000e+00, ptr [[MIN1]], align 8 +// LNX-NEXT: store double -0.000000e+00, ptr [[MIN2]], align 8 +// LNX-NEXT: store double -0.000000e+00, ptr [[MIN3]], align 8 +// LNX-NEXT: store float 0x7FF8000000000000, ptr [[MIN4]], align 4 +// LNX-NEXT: store float -1.000000e+00, ptr [[MIN5]], align 4 +// LNX-NEXT: store float 0xFFF0000000000000, ptr [[MIN6]], align 4 +// LNX-NEXT: store float 0.000000e+00, ptr [[MIN7]], align 4 +// LNX-NEXT: store x86_fp80 0xK4005F6E978D4FDF3B646, ptr [[MIN8]], align 16 +// LNX-NEXT: store double 1.524000e+01, ptr [[MAX1]], align 8 +// LNX-NEXT: store double 0.000000e+00, ptr [[MAX2]], align 8 +// LNX-NEXT: store double 0.000000e+00, ptr [[MAX3]], align 8 +// LNX-NEXT: store float -1.000000e+00, ptr [[MAX4]], align 4 +// LNX-NEXT: store float 0x7FF0000000000000, ptr [[MAX5]], align 4 +// LNX-NEXT: store float 0.000000e+00, ptr [[MAX6]], align 4 +// LNX-NEXT: store float 0x7FF8000000000000, ptr [[MAX7]], align 4 +// LNX-NEXT: store x86_fp80 0xK4008C540C49BA5E353F8, ptr [[MAX8]], align 16 +// LNX-NEXT: store double 0x3FEEDCCCCCCCCCCD, ptr [[FREXP1]], align 8 +// LNX-NEXT: store double 0.000000e+00, ptr [[FREXP2]], align 8 +// LNX-NEXT: store double -0.000000e+00, ptr [[FREXP3]], align 8 +// LNX-NEXT: store float 0x7FF8000000000000, ptr [[FREXP4]], align 4 +// LNX-NEXT: store float 0xFFF8000000000000, ptr [[FREXP5]], align 4 +// LNX-NEXT: store float 0x7FF0000000000000, ptr [[FREXP6]], align 4 +// LNX-NEXT: store float 0x7FF0000000000000, ptr [[FREXP7]], align 4 +// LNX-NEXT: store x86_fp80 0xK3FFE81A9FBE76C8B4396, ptr [[FREXP8]], align 16 // LNX-NEXT: ret i32 0 // int func() @@ -96,24 +128,34 @@ 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); + constexpr double min1 = __builtin_fmin(15.24, 1.3); + constexpr double min2 = __builtin_fmin(-0.0, +0.0); + constexpr double min3 = __builtin_fmin(+0.0, -0.0); + constexpr float min4 = __builtin_fminf(NAN, NAN); + constexpr float min5 = __builtin_fminf(NAN, -1); + constexpr float min6 = __builtin_fminf(-INFINITY, 0); + constexpr float min7 = __builtin_fminf(INFINITY, 0); + constexpr long double min8 = __builtin_fminl(123.456L, 789.012L); + + // fmax + constexpr double max1 = __builtin_fmax(15.24, 1.3); + constexpr double max2 = __builtin_fmax(-0.0, +0.0); + constexpr double max3 = __builtin_fmax(+0.0, -0.0); + constexpr float max4 = __builtin_fmaxf(NAN, -1); + constexpr float max5 = __builtin_fmaxf(+INFINITY, 0); + constexpr float max6 = __builtin_fmaxf(-INFINITY, 0); + constexpr float max7 = __builtin_fmaxf(NAN, NAN); + constexpr long double max8 = __builtin_fmaxl(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 float f12 = __builtin_frexpf(NAN, &i); - constexpr float f13 = __builtin_frexpf(-NAN, &i); - constexpr float f14 = __builtin_frexpf(INFINITY, &i); - constexpr float f15 = __builtin_frexpf(INFINITY, &i); - constexpr long double f16 = __builtin_frexpl(259.328L, &i); + constexpr double frexp1 = __builtin_frexp(123.45, &i); + constexpr double frexp2 = __builtin_frexp(0.0, &i); + constexpr double frexp3 = __builtin_frexp(-0.0, &i); + constexpr float frexp4 = __builtin_frexpf(NAN, &i); + constexpr float frexp5 = __builtin_frexpf(-NAN, &i); + constexpr float frexp6 = __builtin_frexpf(INFINITY, &i); + constexpr float frexp7 = __builtin_frexpf(INFINITY, &i); + constexpr long double frexp8 = __builtin_frexpl(259.328L, &i); return 0; } diff --git a/clang/test/SemaCXX/constexpr-math.cpp b/clang/test/SemaCXX/constexpr-math.cpp index 2c4c29c1c6542..7ad7618f3df14 100644 --- a/clang/test/SemaCXX/constexpr-math.cpp +++ b/clang/test/SemaCXX/constexpr-math.cpp @@ -26,6 +26,17 @@ int main() { static_assert(is_same_val<__builtin_fminf(+INFINITY, 0), 0.f>); static_assert(is_same_val<__builtin_fminf(-INFINITY, 0), -INFINITY>); static_assert(is_same_val<__builtin_fminf(NAN, NAN), NAN>); + static_assert(is_same_val<__builtin_fminl(123.456L, 789.012L), 123.456L>); + + // fmax + static_assert(is_same_val<__builtin_fmax(15.24, 1.3), 15.24>); + static_assert(is_same_val<__builtin_fmax(-0.0, +0.0), +0.0>); + static_assert(is_same_val<__builtin_fmax(+0.0, -0.0), +0.0>); + static_assert(is_same_val<__builtin_fmaxf(NAN, -1), -1.f>); + static_assert(is_same_val<__builtin_fmaxf(+INFINITY, 0), INFINITY>); + static_assert(is_same_val<__builtin_fmaxf(-INFINITY, 0), 0.f>); + static_assert(is_same_val<__builtin_fmaxf(NAN, NAN), NAN>); + static_assert(is_same_val<__builtin_fmaxl(123.456L, 789.012L), 789.012L>); // frexp static_assert(is_same_val<__builtin_frexp(123.45, &i), 123.45/128>); @@ -35,6 +46,7 @@ int main() { static_assert(is_same_val<__builtin_frexpf(-NAN, &i), -NAN>); static_assert(is_same_val<__builtin_frexpf(INFINITY, &i), INFINITY>); static_assert(is_same_val<__builtin_frexpf(-INFINITY, &i), -INFINITY>); - + static_assert(is_same_val<__builtin_frexpl(123.45L, &i), 123.45L/128>); + return 0; } diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h index deb74cb2fdeb1..c9097b4f4e607 100644 --- a/llvm/include/llvm/ADT/APFloat.h +++ b/llvm/include/llvm/ADT/APFloat.h @@ -951,6 +951,19 @@ class APFloat : public APFloatBase { bool needsCleanup() const { APFLOAT_DISPATCH_ON_SEMANTICS(needsCleanup()); } + // Checks that the value x is in the range (-1;-0.5], [0.5; 1) + static bool isInRange(const llvm::APFloat &x) { + llvm::APFloat minusOne(x.getSemantics(), "-1.0"); + llvm::APFloat minusHalf(x.getSemantics(), "-0.5"); + llvm::APFloat half(x.getSemantics(), "0.5"); + llvm::APFloat one(x.getSemantics(), "1.0"); + + return ((x.compare(minusOne) == llvm::APFloat::cmpGreaterThan && + x.compare(minusHalf) != llvm::APFloat::cmpGreaterThan) || + (x.compare(half) != llvm::APFloat::cmpLessThan && + x.compare(one) == llvm::APFloat::cmpLessThan)); + } + /// Factory for Positive and Negative Zero. /// /// \param Negative True iff the number should be negative. >From 1793cf076c74fb7a6769674f91a3d1fb9aa19ee4 Mon Sep 17 00:00:00 2001 From: Zahira Ammarguellat <zahira.ammarguel...@intel.com> Date: Fri, 10 May 2024 07:14:19 -0700 Subject: [PATCH 6/8] Addressed review comments. --- clang/lib/AST/ExprConstant.cpp | 18 +++++++++++++++--- llvm/include/llvm/ADT/APFloat.h | 13 ------------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 3a4abab8fd336..f82ae8ec1a890 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -14540,6 +14540,18 @@ static bool TryEvaluateBuiltinNaN(const ASTContext &Context, return true; } +// Checks that the value x is in the range (-1;-0.5], [0.5; 1) +static bool isInFrexpResultRange(const llvm::APFloat &x) { + llvm::APFloat minusOne(x.getSemantics(), "-1.0"); + llvm::APFloat minusHalf(x.getSemantics(), "-0.5"); + llvm::APFloat half(x.getSemantics(), "0.5"); + llvm::APFloat one(x.getSemantics(), "1.0"); + + return ((x.compare(minusOne) == llvm::APFloat::cmpGreaterThan && + x.compare(minusHalf) != llvm::APFloat::cmpGreaterThan) || + (x.compare(half) != llvm::APFloat::cmpLessThan && + x.compare(one) == llvm::APFloat::cmpLessThan)); +} void FloatExprEvaluator::StoreExponent(LValue Pointer, int exp) { const APValue::LValueBase Base = Pointer.getLValueBase(); @@ -14572,9 +14584,9 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { int FrexpExp; llvm::RoundingMode RM = getActiveRoundingMode(Info, E); Result = llvm::frexp(Result, FrexpExp, RM); - if (!Result.isZero() && !Result.isNaN() && !Result.isInfinity()) - assert(llvm::APFloat::isInRange(Result) && - "The value is not in the expected range for frexp."); + assert((Result.isZero() || Result.isNaN() || Result.isInfinity() || + isInFrexpResultRange(Result)) && + "The value is not in the expected range for frexp."); StoreExponent(Pointer, FrexpExp); return true; } diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h index c9097b4f4e607..deb74cb2fdeb1 100644 --- a/llvm/include/llvm/ADT/APFloat.h +++ b/llvm/include/llvm/ADT/APFloat.h @@ -951,19 +951,6 @@ class APFloat : public APFloatBase { bool needsCleanup() const { APFLOAT_DISPATCH_ON_SEMANTICS(needsCleanup()); } - // Checks that the value x is in the range (-1;-0.5], [0.5; 1) - static bool isInRange(const llvm::APFloat &x) { - llvm::APFloat minusOne(x.getSemantics(), "-1.0"); - llvm::APFloat minusHalf(x.getSemantics(), "-0.5"); - llvm::APFloat half(x.getSemantics(), "0.5"); - llvm::APFloat one(x.getSemantics(), "1.0"); - - return ((x.compare(minusOne) == llvm::APFloat::cmpGreaterThan && - x.compare(minusHalf) != llvm::APFloat::cmpGreaterThan) || - (x.compare(half) != llvm::APFloat::cmpLessThan && - x.compare(one) == llvm::APFloat::cmpLessThan)); - } - /// Factory for Positive and Negative Zero. /// /// \param Negative True iff the number should be negative. >From 42d7d4c55d3a163993e0f3cfde73244986e81c9f Mon Sep 17 00:00:00 2001 From: Zahira Ammarguellat <zahira.ammarguel...@intel.com> Date: Wed, 15 May 2024 08:14:10 -0700 Subject: [PATCH 7/8] Added a fix for failing LIT test. --- clang/lib/AST/ExprConstant.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index f82ae8ec1a890..b1005ed756f7e 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -14574,9 +14574,17 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { default: return false; + case Builtin::BI__builtin_frexpl: + // AIX library function `frexpl` has 'long double' type and not + // PPCDoubleDouble type. To make sure we generate the right value, don't + // constant evaluate it and instead defer to a libcall. + if (Info.Ctx.getTargetInfo().getTriple().isPPC() && + (&Info.Ctx.getTargetInfo().getLongDoubleFormat() != + &llvm::APFloat::PPCDoubleDouble())) + return false; + LLVM_FALLTHROUGH; case Builtin::BI__builtin_frexp: - case Builtin::BI__builtin_frexpf: - case Builtin::BI__builtin_frexpl: { + case Builtin::BI__builtin_frexpf: { LValue Pointer; if (!EvaluateFloat(E->getArg(0), Result, Info) || !EvaluatePointer(E->getArg(1), Pointer, Info)) @@ -14590,6 +14598,7 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { StoreExponent(Pointer, FrexpExp); return true; } + case Builtin::BI__builtin_huge_val: case Builtin::BI__builtin_huge_valf: case Builtin::BI__builtin_huge_vall: @@ -14663,9 +14672,6 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { return true; } - case Builtin::BIfmax: - case Builtin::BIfmaxf: - case Builtin::BIfmaxl: case Builtin::BI__builtin_fmax: case Builtin::BI__builtin_fmaxf: case Builtin::BI__builtin_fmaxl: @@ -14684,9 +14690,6 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { return true; } - case Builtin::BIfmin: - case Builtin::BIfminf: - case Builtin::BIfminl: case Builtin::BI__builtin_fmin: case Builtin::BI__builtin_fminf: case Builtin::BI__builtin_fminl: >From 9f4d6328ae03488421432fbdcba0d3166285c550 Mon Sep 17 00:00:00 2001 From: Zahira Ammarguellat <zahira.ammarguel...@intel.com> Date: Fri, 17 May 2024 05:17:24 -0700 Subject: [PATCH 8/8] Fixed aix-builtin-mapping.c test. --- clang/lib/AST/ExprConstant.cpp | 12 ++---------- clang/test/CodeGen/aix-builtin-mapping.c | 8 ++++++-- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index b1005ed756f7e..6fbd46606d627 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -14574,17 +14574,9 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { default: return false; - case Builtin::BI__builtin_frexpl: - // AIX library function `frexpl` has 'long double' type and not - // PPCDoubleDouble type. To make sure we generate the right value, don't - // constant evaluate it and instead defer to a libcall. - if (Info.Ctx.getTargetInfo().getTriple().isPPC() && - (&Info.Ctx.getTargetInfo().getLongDoubleFormat() != - &llvm::APFloat::PPCDoubleDouble())) - return false; - LLVM_FALLTHROUGH; case Builtin::BI__builtin_frexp: - case Builtin::BI__builtin_frexpf: { + 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)) diff --git a/clang/test/CodeGen/aix-builtin-mapping.c b/clang/test/CodeGen/aix-builtin-mapping.c index a79218c6f1d8b..1936f23b71d52 100644 --- a/clang/test/CodeGen/aix-builtin-mapping.c +++ b/clang/test/CodeGen/aix-builtin-mapping.c @@ -6,6 +6,8 @@ // RUN: %clang_cc1 -triple powerpc-ibm-aix -mlong-double-64 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK %s // RUN: %clang_cc1 -triple powerpc64-ibm-aix -mlong-double-64 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK %s +long double input = 0.0L; + int main() { int DummyInt; @@ -13,10 +15,12 @@ int main() long double returnValue; returnValue = __builtin_modfl(1.0L, &DummyLongDouble); - returnValue = __builtin_frexpl(0.0L, &DummyInt); + returnValue = __builtin_frexpl(input, &DummyInt); returnValue = __builtin_ldexpl(1.0L, 1); } +// CHECK: @input = global double 0.000000e+00 // CHECK: %call = call double @modf(double noundef 1.000000e+00, ptr noundef %DummyLongDouble) #3 -// CHECK: %{{.+}} = call { double, i32 } @llvm.frexp.f64.i32(double 0.000000e+00) +// CHECK: [[TMP0:%.*]] = load double, ptr @input +// CHECK: %{{.+}} = call { double, i32 } @llvm.frexp.f64.i32(double [[TMP0]]) // CHECK: %{{.+}} = call double @llvm.ldexp.f64.i32(double 1.000000e+00, i32 1) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits