Clang: Support minimumnum and maximumnum intrinsics (#96281)
We just introduce llvm.minimumnum and llvm.maximumnum intrinsics support to llvm. Let's support them in Clang. See: #93033
This commit is contained in:
parent
4b31568e02
commit
5bf81e53db
@ -215,6 +215,18 @@ def FminF16F128 : Builtin, F16F128MathTemplate {
|
||||
let Prototype = "T(T, T)";
|
||||
}
|
||||
|
||||
def FmaximumNumF16F128 : Builtin, F16F128MathTemplate {
|
||||
let Spellings = ["__builtin_fmaximum_num"];
|
||||
let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const, Constexpr];
|
||||
let Prototype = "T(T, T)";
|
||||
}
|
||||
|
||||
def FminimumNumF16F128 : Builtin, F16F128MathTemplate {
|
||||
let Spellings = ["__builtin_fminimum_num"];
|
||||
let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const, Constexpr];
|
||||
let Prototype = "T(T, T)";
|
||||
}
|
||||
|
||||
def Atan2F128 : Builtin {
|
||||
let Spellings = ["__builtin_atan2f128"];
|
||||
let Attributes = [FunctionWithBuiltinPrefix, NoThrow, ConstIgnoringErrnoAndExceptions];
|
||||
@ -3728,6 +3740,22 @@ def Fmin : FPMathTemplate, LibBuiltin<"math.h"> {
|
||||
let OnlyBuiltinPrefixedAliasIsConstexpr = 1;
|
||||
}
|
||||
|
||||
def FmaximumNum : FPMathTemplate, LibBuiltin<"math.h"> {
|
||||
let Spellings = ["fmaximum_num"];
|
||||
let Attributes = [NoThrow, Const];
|
||||
let Prototype = "T(T, T)";
|
||||
let AddBuiltinPrefixedAlias = 1;
|
||||
let OnlyBuiltinPrefixedAliasIsConstexpr = 1;
|
||||
}
|
||||
|
||||
def FminimumNum : FPMathTemplate, LibBuiltin<"math.h"> {
|
||||
let Spellings = ["fminimum_num"];
|
||||
let Attributes = [NoThrow, Const];
|
||||
let Prototype = "T(T, T)";
|
||||
let AddBuiltinPrefixedAlias = 1;
|
||||
let OnlyBuiltinPrefixedAliasIsConstexpr = 1;
|
||||
}
|
||||
|
||||
def Hypot : FPMathTemplate, LibBuiltin<"math.h"> {
|
||||
let Spellings = ["hypot"];
|
||||
let Attributes = [NoThrow, ConstIgnoringErrnoAndExceptions];
|
||||
|
||||
@ -15310,6 +15310,32 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
|
||||
Result = RHS;
|
||||
return true;
|
||||
}
|
||||
|
||||
case Builtin::BI__builtin_fmaximum_num:
|
||||
case Builtin::BI__builtin_fmaximum_numf:
|
||||
case Builtin::BI__builtin_fmaximum_numl:
|
||||
case Builtin::BI__builtin_fmaximum_numf16:
|
||||
case Builtin::BI__builtin_fmaximum_numf128: {
|
||||
APFloat RHS(0.);
|
||||
if (!EvaluateFloat(E->getArg(0), Result, Info) ||
|
||||
!EvaluateFloat(E->getArg(1), RHS, Info))
|
||||
return false;
|
||||
Result = maximumnum(Result, RHS);
|
||||
return true;
|
||||
}
|
||||
|
||||
case Builtin::BI__builtin_fminimum_num:
|
||||
case Builtin::BI__builtin_fminimum_numf:
|
||||
case Builtin::BI__builtin_fminimum_numl:
|
||||
case Builtin::BI__builtin_fminimum_numf16:
|
||||
case Builtin::BI__builtin_fminimum_numf128: {
|
||||
APFloat RHS(0.);
|
||||
if (!EvaluateFloat(E->getArg(0), Result, Info) ||
|
||||
!EvaluateFloat(E->getArg(1), RHS, Info))
|
||||
return false;
|
||||
Result = minimumnum(Result, RHS);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2869,6 +2869,28 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
|
||||
Intrinsic::minnum,
|
||||
Intrinsic::experimental_constrained_minnum));
|
||||
|
||||
case Builtin::BIfmaximum_num:
|
||||
case Builtin::BIfmaximum_numf:
|
||||
case Builtin::BIfmaximum_numl:
|
||||
case Builtin::BI__builtin_fmaximum_num:
|
||||
case Builtin::BI__builtin_fmaximum_numf:
|
||||
case Builtin::BI__builtin_fmaximum_numf16:
|
||||
case Builtin::BI__builtin_fmaximum_numl:
|
||||
case Builtin::BI__builtin_fmaximum_numf128:
|
||||
return RValue::get(
|
||||
emitBuiltinWithOneOverloadedType<2>(*this, E, Intrinsic::maximumnum));
|
||||
|
||||
case Builtin::BIfminimum_num:
|
||||
case Builtin::BIfminimum_numf:
|
||||
case Builtin::BIfminimum_numl:
|
||||
case Builtin::BI__builtin_fminimum_num:
|
||||
case Builtin::BI__builtin_fminimum_numf:
|
||||
case Builtin::BI__builtin_fminimum_numf16:
|
||||
case Builtin::BI__builtin_fminimum_numl:
|
||||
case Builtin::BI__builtin_fminimum_numf128:
|
||||
return RValue::get(
|
||||
emitBuiltinWithOneOverloadedType<2>(*this, E, Intrinsic::minimumnum));
|
||||
|
||||
// fmod() is a special-case. It maps to the frem instruction rather than an
|
||||
// LLVM intrinsic.
|
||||
case Builtin::BIfmod:
|
||||
|
||||
@ -69,6 +69,13 @@ int main(void) {
|
||||
P(issignaling, (1.));
|
||||
P(isfpclass, (1., 1));
|
||||
|
||||
Q(fmaximum_num, (1.0, 2.0));
|
||||
Q(fmaximum_numf, (1.0, 2.0));
|
||||
Q(fmaximum_numl, (1.0, 2.0));
|
||||
Q(fminimum_num, (1.0, 2.0));
|
||||
Q(fminimum_numf, (1.0, 2.0));
|
||||
Q(fminimum_numl, (1.0, 2.0));
|
||||
|
||||
// Bitwise & Numeric Functions
|
||||
|
||||
P(abs, (N));
|
||||
@ -305,7 +312,7 @@ void test_float_builtins(__fp16 *H, float F, double D, long double LD) {
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define{{.*}} void @test_float_builtin_ops
|
||||
void test_float_builtin_ops(float F, double D, long double LD) {
|
||||
void test_float_builtin_ops(float F, double D, long double LD, int I) {
|
||||
volatile float resf;
|
||||
volatile double resd;
|
||||
volatile long double resld;
|
||||
@ -353,6 +360,58 @@ void test_float_builtin_ops(float F, double D, long double LD) {
|
||||
resld = __builtin_fmaxl(LD, LD);
|
||||
// CHECK: call x86_fp80 @llvm.maxnum.f80
|
||||
|
||||
resf = __builtin_fminimum_numf(F, F);
|
||||
// CHECK: call float @llvm.minimumnum.f32
|
||||
|
||||
resf = __builtin_fminimum_numf(I, I);
|
||||
// CHECK: sitofp i32 {{%[0-9]+}} to float
|
||||
// CHECK: sitofp i32 {{%[0-9]+}} to float
|
||||
// CHECK: call float @llvm.minimumnum.f32
|
||||
|
||||
resf = __builtin_fminimum_numf(1.0, 2.0);
|
||||
// CHECK: store volatile float 1.000000e+00, ptr %resf
|
||||
|
||||
resd = __builtin_fminimum_num(D, D);
|
||||
// CHECK: call double @llvm.minimumnum.f64
|
||||
|
||||
resd = __builtin_fminimum_num(I, I);
|
||||
// CHECK: sitofp i32 {{%[0-9]+}} to double
|
||||
// CHECK: sitofp i32 {{%[0-9]+}} to double
|
||||
// CHECK: call double @llvm.minimumnum.f64
|
||||
|
||||
resd = __builtin_fminimum_num(1.0, 2.0);
|
||||
// CHECK: store volatile double 1.000000e+00, ptr %resd
|
||||
|
||||
//FIXME: __builtin_fminimum_numl is not supported well yet.
|
||||
resld = __builtin_fminimum_numl(1.0, 2.0);
|
||||
// CHECK: store volatile x86_fp80 0xK3FFF8000000000000000, ptr %resld, align 16
|
||||
|
||||
resf = __builtin_fmaximum_numf(F, F);
|
||||
// CHECK: call float @llvm.maximumnum.f32
|
||||
|
||||
resf = __builtin_fmaximum_numf(I, I);
|
||||
// CHECK: sitofp i32 {{%[0-9]+}} to float
|
||||
// CHECK: sitofp i32 {{%[0-9]+}} to float
|
||||
// CHECK: call float @llvm.maximumnum.f32
|
||||
|
||||
resf = __builtin_fmaximum_numf(1.0, 2.0);
|
||||
// CHECK: store volatile float 2.000000e+00, ptr %resf
|
||||
|
||||
resd = __builtin_fmaximum_num(D, D);
|
||||
// CHECK: call double @llvm.maximumnum.f64
|
||||
|
||||
resd = __builtin_fmaximum_num(I, I);
|
||||
// CHECK: sitofp i32 {{%[0-9]+}} to double
|
||||
// CHECK: sitofp i32 {{%[0-9]+}} to double
|
||||
// CHECK: call double @llvm.maximumnum.f64
|
||||
|
||||
resd = __builtin_fmaximum_num(1.0, 2.0);
|
||||
// CHECK: store volatile double 2.000000e+00, ptr %resd
|
||||
|
||||
//FIXME: __builtin_fmaximum_numl is not supported well yet.
|
||||
resld = __builtin_fmaximum_numl(1.0, 2.0);
|
||||
// CHECK: store volatile x86_fp80 0xK40008000000000000000, ptr %resld, align 16
|
||||
|
||||
resf = __builtin_fabsf(F);
|
||||
// CHECK: call float @llvm.fabs.f32
|
||||
|
||||
|
||||
33
clang/test/CodeGen/fmaxfmin-invalid-arguments-type.c
Normal file
33
clang/test/CodeGen/fmaxfmin-invalid-arguments-type.c
Normal file
@ -0,0 +1,33 @@
|
||||
// RUN: not %clang_cc1 -triple x86_64 %s -fsyntax-only -verify 2>&1 | FileCheck %s --check-prefix=CHECK-ERR
|
||||
|
||||
float fminimum_numf (float, float);
|
||||
double fminimum_num (double, double);
|
||||
long double fminimum_numl (long double, long double);
|
||||
float fmaximum_numf (float, float);
|
||||
double fmaximum_num (double, double);
|
||||
long double fmaximum_numl (long double, long double);
|
||||
|
||||
// CHECK-ERR: passing 'char *' to parameter of incompatible type 'float'
|
||||
float fmin1(char *a, char *b) {
|
||||
return fminimum_numf(a, b);
|
||||
}
|
||||
// CHECK-ERR: passing 'char *' to parameter of incompatible type 'double'
|
||||
float fmin2(char *a, char *b) {
|
||||
return fminimum_num(a, b);
|
||||
}
|
||||
// CHECK-ERR: passing 'char *' to parameter of incompatible type 'long double'
|
||||
float fmin3(char *a, char *b) {
|
||||
return fminimum_numl(a, b);
|
||||
}
|
||||
// CHECK-ERR: passing 'char *' to parameter of incompatible type 'float'
|
||||
float fmax1(char *a, char *b) {
|
||||
return fmaximum_numf(a, b);
|
||||
}
|
||||
// CHECK-ERR: passing 'char *' to parameter of incompatible type 'double'
|
||||
float fmax2(char *a, char *b) {
|
||||
return fmaximum_num(a, b);
|
||||
}
|
||||
// CHECK-ERR: passing 'char *' to parameter of incompatible type 'long double'
|
||||
float fmax3(char *a, char *b) {
|
||||
return fmaximum_numl(a, b);
|
||||
}
|
||||
@ -1,8 +1,8 @@
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-implicit-function-declaration -w -o - -emit-llvm %s | FileCheck %s --check-prefix=NO__ERRNO
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-implicit-function-declaration -w -o - -emit-llvm -fmath-errno %s | FileCheck %s --check-prefix=HAS_ERRNO
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-implicit-function-declaration -w -o - -emit-llvm -disable-llvm-passes -O2 %s | FileCheck %s --check-prefix=NO__ERRNO
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-implicit-function-declaration -w -o - -emit-llvm -disable-llvm-passes -O2 -fmath-errno %s | FileCheck %s --check-prefix=HAS_ERRNO
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-implicit-function-declaration -w -o - -emit-llvm -ffp-exception-behavior=maytrap %s | FileCheck %s --check-prefix=HAS_MAYTRAP
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-implicit-function-declaration -w -o - -emit-llvm %s | FileCheck %s --check-prefixes=COMMON,NO__ERRNO
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-implicit-function-declaration -w -o - -emit-llvm -fmath-errno %s | FileCheck %s --check-prefixes=COMMON,HAS_ERRNO
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-implicit-function-declaration -w -o - -emit-llvm -disable-llvm-passes -O2 %s | FileCheck %s --check-prefixes=COMMON,NO__ERRNO
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-implicit-function-declaration -w -o - -emit-llvm -disable-llvm-passes -O2 -fmath-errno %s | FileCheck %s --check-prefixes=COMMON,HAS_ERRNO
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -Wno-implicit-function-declaration -w -o - -emit-llvm -ffp-exception-behavior=maytrap %s | FileCheck %s --check-prefixes=COMMON,HAS_MAYTRAP
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-unknown-gnu -Wno-implicit-function-declaration -w -o - -emit-llvm -fmath-errno %s | FileCheck %s --check-prefix=HAS_ERRNO_GNU
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -Wno-implicit-function-declaration -w -o - -emit-llvm -fmath-errno %s | FileCheck %s --check-prefix=HAS_ERRNO_WIN
|
||||
|
||||
@ -372,6 +372,18 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
|
||||
// HAS_MAYTRAP: declare float @llvm.experimental.constrained.minnum.f32(
|
||||
// HAS_MAYTRAP: declare x86_fp80 @llvm.experimental.constrained.minnum.f80(
|
||||
|
||||
fmaximum_num(*d,*d); fmaximum_numf(f,f); fmaximum_numl(*l,*l);
|
||||
|
||||
// COMMON: declare double @llvm.maximumnum.f64(double, double) [[READNONE_INTRINSIC]]
|
||||
// COMMON: declare float @llvm.maximumnum.f32(float, float) [[READNONE_INTRINSIC]]
|
||||
// COMMON: declare x86_fp80 @llvm.maximumnum.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]]
|
||||
|
||||
fminimum_num(*d,*d); fminimum_numf(f,f); fminimum_numl(*l,*l);
|
||||
|
||||
// COMMON: declare double @llvm.minimumnum.f64(double, double) [[READNONE_INTRINSIC]]
|
||||
// COMMON: declare float @llvm.minimumnum.f32(float, float) [[READNONE_INTRINSIC]]
|
||||
// COMMON: declare x86_fp80 @llvm.minimumnum.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]]
|
||||
|
||||
hypot(f,f); hypotf(f,f); hypotl(f,f);
|
||||
|
||||
// NO__ERRNO: declare double @hypot(double noundef, double noundef) [[READNONE]]
|
||||
|
||||
@ -58,7 +58,9 @@
|
||||
|
||||
// Check __has_constexpr_builtin
|
||||
#if !__has_constexpr_builtin(__builtin_fmax) || \
|
||||
!__has_constexpr_builtin(__builtin_fmin)
|
||||
!__has_constexpr_builtin(__builtin_fmin) || \
|
||||
!__has_constexpr_builtin(__builtin_fmaximum_num) || \
|
||||
!__has_constexpr_builtin(__builtin_fminimum_num)
|
||||
#error Clang should have these constexpr builtins
|
||||
#endif
|
||||
|
||||
|
||||
69
clang/test/Sema/constant-builtins-fmaximum-num.cpp
Normal file
69
clang/test/Sema/constant-builtins-fmaximum-num.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
|
||||
// FIXME: %clang_cc1 -std=c++17 -fsyntax-only -verify -fexperimental-new-constant-interpreter %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
constexpr double NaN = __builtin_nan("");
|
||||
constexpr double SNaN = __builtin_nans("");
|
||||
constexpr double Inf = __builtin_inf();
|
||||
constexpr double NegInf = -__builtin_inf();
|
||||
|
||||
#define FMAXIMUMNUM_TEST_SIMPLE(T, FUNC) \
|
||||
static_assert(T(6.7890) == FUNC(T(1.2345), T(6.7890))); \
|
||||
static_assert(T(6.7890) == FUNC(T(6.7890), T(1.2345)));
|
||||
|
||||
#define FMAXIMUMNUM_TEST_SNAN(T, FUNC) \
|
||||
static_assert(Inf == FUNC(SNaN, Inf)); \
|
||||
static_assert(NegInf == FUNC(NegInf, SNaN)); \
|
||||
static_assert(0.0 == FUNC(SNaN, 0.0)); \
|
||||
static_assert(-0.0 == FUNC(-0.0, SNaN)); \
|
||||
static_assert(T(-1.2345) == FUNC(SNaN, T(-1.2345))); \
|
||||
static_assert(T(1.2345) == FUNC(T(1.2345), SNaN)); \
|
||||
static_assert(__builtin_isnan(FUNC(SNaN, SNaN))); \
|
||||
static_assert(__builtin_isnan(FUNC(NaN, SNaN))); \
|
||||
static_assert(!__builtin_issignaling(FUNC(SNaN, SNaN))); \
|
||||
static_assert(!__builtin_issignaling(FUNC(NaN, SNaN)));
|
||||
|
||||
#define FMAXIMUMNUM_TEST_NAN(T, FUNC) \
|
||||
static_assert(Inf == FUNC(NaN, Inf)); \
|
||||
static_assert(NegInf == FUNC(NegInf, NaN)); \
|
||||
static_assert(0.0 == FUNC(NaN, 0.0)); \
|
||||
static_assert(-0.0 == FUNC(-0.0, NaN)); \
|
||||
static_assert(T(-1.2345) == FUNC(NaN, T(-1.2345))); \
|
||||
static_assert(T(1.2345) == FUNC(T(1.2345), NaN)); \
|
||||
static_assert(__builtin_isnan(FUNC(NaN, NaN)));
|
||||
|
||||
#define FMAXIMUMNUM_TEST_INF(T, FUNC) \
|
||||
static_assert(Inf == FUNC(NegInf, Inf)); \
|
||||
static_assert(Inf == FUNC(Inf, 0.0)); \
|
||||
static_assert(Inf == FUNC(-0.0, Inf)); \
|
||||
static_assert(Inf == FUNC(Inf, T(1.2345))); \
|
||||
static_assert(Inf == FUNC(T(-1.2345), Inf));
|
||||
|
||||
#define FMAXIMUMNUM_TEST_NEG_INF(T, FUNC) \
|
||||
static_assert(Inf == FUNC(Inf, NegInf)); \
|
||||
static_assert(0.0 == FUNC(NegInf, 0.0)); \
|
||||
static_assert(-0.0 == FUNC(-0.0, NegInf)); \
|
||||
static_assert(T(-1.2345) == FUNC(NegInf, T(-1.2345))); \
|
||||
static_assert(T(1.2345) == FUNC(T(1.2345), NegInf));
|
||||
|
||||
#define FMAXIMUMNUM_TEST_BOTH_ZERO(T, FUNC) \
|
||||
static_assert(__builtin_copysign(1.0, FUNC(0.0, 0.0)) == 1.0); \
|
||||
static_assert(__builtin_copysign(1.0, FUNC(-0.0, 0.0)) == 1.0); \
|
||||
static_assert(__builtin_copysign(1.0, FUNC(0.0, -0.0)) == 1.0); \
|
||||
static_assert(__builtin_copysign(1.0, FUNC(-0.0, -0.0)) == -1.0);
|
||||
|
||||
#define LIST_FMAXIMUMNUM_TESTS(T, FUNC) \
|
||||
FMAXIMUMNUM_TEST_SIMPLE(T, FUNC) \
|
||||
FMAXIMUMNUM_TEST_NAN(T, FUNC) \
|
||||
FMAXIMUMNUM_TEST_SNAN(T, FUNC) \
|
||||
FMAXIMUMNUM_TEST_INF(T, FUNC) \
|
||||
FMAXIMUMNUM_TEST_NEG_INF(T, FUNC) \
|
||||
FMAXIMUMNUM_TEST_BOTH_ZERO(T, FUNC)
|
||||
|
||||
LIST_FMAXIMUMNUM_TESTS(double, __builtin_fmaximum_num)
|
||||
LIST_FMAXIMUMNUM_TESTS(float, __builtin_fmaximum_numf)
|
||||
LIST_FMAXIMUMNUM_TESTS((long double), __builtin_fmaximum_numl)
|
||||
LIST_FMAXIMUMNUM_TESTS(__fp16, __builtin_fmaximum_numf16)
|
||||
#ifdef __FLOAT128__
|
||||
LIST_FMAXIMUMNUM_TESTS(__float128, __builtin_fmaximum_numf128)
|
||||
#endif
|
||||
69
clang/test/Sema/constant-builtins-fminimum-num.cpp
Normal file
69
clang/test/Sema/constant-builtins-fminimum-num.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
|
||||
// FIXME: %clang_cc1 -std=c++17 -fsyntax-only -verify -fexperimental-new-constant-interpreter %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
constexpr double NaN = __builtin_nan("");
|
||||
constexpr double SNaN = __builtin_nans("");
|
||||
constexpr double Inf = __builtin_inf();
|
||||
constexpr double NegInf = -__builtin_inf();
|
||||
|
||||
#define FMINIMUMNUM_TEST_SIMPLE(T, FUNC) \
|
||||
static_assert(T(1.2345) == FUNC(T(1.2345), T(6.7890))); \
|
||||
static_assert(T(1.2345) == FUNC(T(6.7890), T(1.2345)));
|
||||
|
||||
#define FMINIMUMNUM_TEST_NAN(T, FUNC) \
|
||||
static_assert(Inf == FUNC(NaN, Inf)); \
|
||||
static_assert(NegInf == FUNC(NegInf, NaN)); \
|
||||
static_assert(0.0 == FUNC(NaN, 0.0)); \
|
||||
static_assert(-0.0 == FUNC(-0.0, NaN)); \
|
||||
static_assert(T(-1.2345) == FUNC(NaN, T(-1.2345))); \
|
||||
static_assert(T(1.2345) == FUNC(T(1.2345), NaN)); \
|
||||
static_assert(__builtin_isnan(FUNC(NaN, NaN)));
|
||||
|
||||
#define FMINIMUMNUM_TEST_SNAN(T, FUNC) \
|
||||
static_assert(Inf == FUNC(SNaN, Inf)); \
|
||||
static_assert(NegInf == FUNC(NegInf, SNaN)); \
|
||||
static_assert(0.0 == FUNC(SNaN, 0.0)); \
|
||||
static_assert(-0.0 == FUNC(-0.0, SNaN)); \
|
||||
static_assert(T(-1.2345) == FUNC(SNaN, T(-1.2345))); \
|
||||
static_assert(T(1.2345) == FUNC(T(1.2345), SNaN)); \
|
||||
static_assert(__builtin_isnan(FUNC(SNaN, SNaN))); \
|
||||
static_assert(__builtin_isnan(FUNC(NaN, SNaN))); \
|
||||
static_assert(!__builtin_issignaling(FUNC(SNaN, SNaN))); \
|
||||
static_assert(!__builtin_issignaling(FUNC(NaN, SNaN)));
|
||||
|
||||
#define FMINIMUMNUM_TEST_INF(T, FUNC) \
|
||||
static_assert(NegInf == FUNC(NegInf, Inf)); \
|
||||
static_assert(0.0 == FUNC(Inf, 0.0)); \
|
||||
static_assert(-0.0 == FUNC(-0.0, Inf)); \
|
||||
static_assert(T(1.2345) == FUNC(Inf, T(1.2345))); \
|
||||
static_assert(T(-1.2345) == FUNC(T(-1.2345), Inf));
|
||||
|
||||
#define FMINIMUMNUM_TEST_NEG_INF(T, FUNC) \
|
||||
static_assert(NegInf == FUNC(Inf, NegInf)); \
|
||||
static_assert(NegInf == FUNC(NegInf, 0.0)); \
|
||||
static_assert(NegInf == FUNC(-0.0, NegInf)); \
|
||||
static_assert(NegInf == FUNC(NegInf, T(-1.2345))); \
|
||||
static_assert(NegInf == FUNC(T(1.2345), NegInf));
|
||||
|
||||
#define FMINIMUMNUM_TEST_BOTH_ZERO(T, FUNC) \
|
||||
static_assert(__builtin_copysign(1.0, FUNC(0.0, 0.0)) == 1.0); \
|
||||
static_assert(__builtin_copysign(1.0, FUNC(-0.0, 0.0)) == -1.0); \
|
||||
static_assert(__builtin_copysign(1.0, FUNC(0.0, -0.0)) == -1.0); \
|
||||
static_assert(__builtin_copysign(1.0, FUNC(-0.0, -0.0)) == -1.0);
|
||||
|
||||
#define LIST_FMINIMUMNUM_TESTS(T, FUNC) \
|
||||
FMINIMUMNUM_TEST_SIMPLE(T, FUNC) \
|
||||
FMINIMUMNUM_TEST_NAN(T, FUNC) \
|
||||
FMINIMUMNUM_TEST_SNAN(T, FUNC) \
|
||||
FMINIMUMNUM_TEST_INF(T, FUNC) \
|
||||
FMINIMUMNUM_TEST_NEG_INF(T, FUNC) \
|
||||
FMINIMUMNUM_TEST_BOTH_ZERO(T, FUNC)
|
||||
|
||||
LIST_FMINIMUMNUM_TESTS(double, __builtin_fminimum_num)
|
||||
LIST_FMINIMUMNUM_TESTS(float, __builtin_fminimum_numf)
|
||||
LIST_FMINIMUMNUM_TESTS((long double), __builtin_fminimum_numl)
|
||||
LIST_FMINIMUMNUM_TESTS(__fp16, __builtin_fminimum_numf16)
|
||||
#ifdef __FLOAT128__
|
||||
LIST_FMINIMUMNUM_TESTS(__float128, __builtin_fminimum_numf128)
|
||||
#endif
|
||||
Loading…
x
Reference in New Issue
Block a user