From: Benjamin Kramer Date: Sat, 6 Jan 2018 21:49:54 +0000 (+0000) Subject: Add support for a limited subset of TS 18661-3 math builtins. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b99f3a83f33074c4b58b5747d72723185d02b8b4;p=clang Add support for a limited subset of TS 18661-3 math builtins. These just overloads for _Float128. They're supported by GCC 7 and used by glibc. APFloat support is already there so just add the overloads. __builtin_copysignf128 __builtin_fabsf128 __builtin_huge_valf128 __builtin_inff128 __builtin_nanf128 __builtin_nansf128 This is the same support that GCC has, according to the documentation, but limited to _Float128. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@321948 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 3d4deb5ed3..00bf1bd7bb 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -48,8 +48,8 @@ // . -> "...". This may only occur at the end of the function list. // // Types may be prefixed with the following modifiers: -// L -> long (e.g. Li for 'long int') -// LL -> long long +// L -> long (e.g. Li for 'long int', Ld for 'long double') +// LL -> long long (e.g. LLi for 'long long int', LLd for __float128) // LLL -> __int128_t (e.g. LLLi) // W -> int64_t // N -> 'int' size if target is LP64, 'L' otherwise. @@ -110,9 +110,11 @@ BUILTIN(__builtin_abs , "ii" , "ncF") BUILTIN(__builtin_copysign, "ddd", "ncF") BUILTIN(__builtin_copysignf, "fff", "ncF") BUILTIN(__builtin_copysignl, "LdLdLd", "ncF") +BUILTIN(__builtin_copysignf128, "LLdLLdLLd", "ncF") BUILTIN(__builtin_fabs , "dd" , "ncF") BUILTIN(__builtin_fabsf, "ff" , "ncF") BUILTIN(__builtin_fabsl, "LdLd", "ncF") +BUILTIN(__builtin_fabsf128, "LLdLLd", "ncF") BUILTIN(__builtin_fmod , "ddd" , "Fne") BUILTIN(__builtin_fmodf, "fff" , "Fne") BUILTIN(__builtin_fmodl, "LdLdLd", "Fne") @@ -122,9 +124,11 @@ BUILTIN(__builtin_frexpl, "LdLdi*", "Fn") BUILTIN(__builtin_huge_val, "d", "nc") BUILTIN(__builtin_huge_valf, "f", "nc") BUILTIN(__builtin_huge_vall, "Ld", "nc") +BUILTIN(__builtin_huge_valf128, "LLd", "nc") BUILTIN(__builtin_inf , "d" , "nc") BUILTIN(__builtin_inff , "f" , "nc") BUILTIN(__builtin_infl , "Ld" , "nc") +BUILTIN(__builtin_inff128 , "LLd" , "nc") BUILTIN(__builtin_labs , "LiLi" , "Fnc") BUILTIN(__builtin_llabs, "LLiLLi", "Fnc") BUILTIN(__builtin_ldexp , "ddi" , "Fne") @@ -136,9 +140,11 @@ BUILTIN(__builtin_modfl, "LdLdLd*", "Fn") BUILTIN(__builtin_nan, "dcC*" , "ncF") BUILTIN(__builtin_nanf, "fcC*" , "ncF") BUILTIN(__builtin_nanl, "LdcC*", "ncF") +BUILTIN(__builtin_nanf128, "LLdcC*", "ncF") BUILTIN(__builtin_nans, "dcC*" , "ncF") BUILTIN(__builtin_nansf, "fcC*" , "ncF") BUILTIN(__builtin_nansl, "LdcC*", "ncF") +BUILTIN(__builtin_nansf128, "LLdcC*", "ncF") BUILTIN(__builtin_powi , "ddi" , "Fnc") BUILTIN(__builtin_powif, "ffi" , "Fnc") BUILTIN(__builtin_powil, "LdLdi", "Fnc") diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index b9a23ed964..2e906247cc 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -8929,10 +8929,12 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, Type = Context.FloatTy; break; case 'd': - assert(HowLong < 2 && !Signed && !Unsigned && + assert(HowLong < 3 && !Signed && !Unsigned && "Bad modifiers used with 'd'!"); - if (HowLong) + if (HowLong == 1) Type = Context.LongDoubleTy; + else if (HowLong == 2) + Type = Context.Float128Ty; else Type = Context.DoubleTy; break; diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 8d9b3c3beb..6cbb498abd 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -9170,9 +9170,11 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BI__builtin_huge_val: case Builtin::BI__builtin_huge_valf: case Builtin::BI__builtin_huge_vall: + case Builtin::BI__builtin_huge_valf128: case Builtin::BI__builtin_inf: case Builtin::BI__builtin_inff: - case Builtin::BI__builtin_infl: { + case Builtin::BI__builtin_infl: + case Builtin::BI__builtin_inff128: { const llvm::fltSemantics &Sem = Info.Ctx.getFloatTypeSemantics(E->getType()); Result = llvm::APFloat::getInf(Sem); @@ -9182,6 +9184,7 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BI__builtin_nans: case Builtin::BI__builtin_nansf: case Builtin::BI__builtin_nansl: + case Builtin::BI__builtin_nansf128: if (!TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0), true, Result)) return Error(E); @@ -9190,6 +9193,7 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BI__builtin_nan: case Builtin::BI__builtin_nanf: case Builtin::BI__builtin_nanl: + case Builtin::BI__builtin_nanf128: // If this is __builtin_nan() turn this into a nan, otherwise we // can't constant fold it. if (!TryEvaluateBuiltinNaN(Info.Ctx, E->getType(), E->getArg(0), @@ -9200,6 +9204,7 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BI__builtin_fabs: case Builtin::BI__builtin_fabsf: case Builtin::BI__builtin_fabsl: + case Builtin::BI__builtin_fabsf128: if (!EvaluateFloat(E->getArg(0), Result, Info)) return false; @@ -9213,7 +9218,8 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BI__builtin_copysign: case Builtin::BI__builtin_copysignf: - case Builtin::BI__builtin_copysignl: { + case Builtin::BI__builtin_copysignl: + case Builtin::BI__builtin_copysignf128: { APFloat RHS(0.); if (!EvaluateFloat(E->getArg(0), Result, Info) || !EvaluateFloat(E->getArg(1), RHS, Info)) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 35ae114c4f..631085a979 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -966,6 +966,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__builtin_copysign: case Builtin::BI__builtin_copysignf: case Builtin::BI__builtin_copysignl: + case Builtin::BI__builtin_copysignf128: return RValue::get(emitBinaryBuiltin(*this, E, Intrinsic::copysign)); case Builtin::BIcos: @@ -998,6 +999,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__builtin_fabs: case Builtin::BI__builtin_fabsf: case Builtin::BI__builtin_fabsl: + case Builtin::BI__builtin_fabsf128: return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::fabs)); case Builtin::BIfloor: diff --git a/test/CodeGen/math-builtins.c b/test/CodeGen/math-builtins.c index 799d91b4ec..89be56dc18 100644 --- a/test/CodeGen/math-builtins.c +++ b/test/CodeGen/math-builtins.c @@ -24,23 +24,27 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) { // HAS_ERRNO: declare float @atan2f(float, float) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[NOT_READNONE]] - __builtin_copysign(f,f); __builtin_copysignf(f,f);__builtin_copysignl(f,f); + __builtin_copysign(f,f); __builtin_copysignf(f,f); __builtin_copysignl(f,f); __builtin_copysignf128(f,f); // NO__ERRNO: declare double @llvm.copysign.f64(double, double) [[READNONE_INTRINSIC:#[0-9]+]] // NO__ERRNO: declare float @llvm.copysign.f32(float, float) [[READNONE_INTRINSIC]] // NO__ERRNO: declare x86_fp80 @llvm.copysign.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare fp128 @llvm.copysign.f128(fp128, fp128) [[READNONE_INTRINSIC]] // HAS_ERRNO: declare double @llvm.copysign.f64(double, double) [[READNONE_INTRINSIC:#[0-9]+]] // HAS_ERRNO: declare float @llvm.copysign.f32(float, float) [[READNONE_INTRINSIC]] // HAS_ERRNO: declare x86_fp80 @llvm.copysign.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare fp128 @llvm.copysign.f128(fp128, fp128) [[READNONE_INTRINSIC]] - __builtin_fabs(f); __builtin_fabsf(f); __builtin_fabsl(f); + __builtin_fabs(f); __builtin_fabsf(f); __builtin_fabsl(f); __builtin_fabsf128(f); // NO__ERRNO: declare double @llvm.fabs.f64(double) [[READNONE_INTRINSIC]] // NO__ERRNO: declare float @llvm.fabs.f32(float) [[READNONE_INTRINSIC]] // NO__ERRNO: declare x86_fp80 @llvm.fabs.f80(x86_fp80) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare fp128 @llvm.fabs.f128(fp128) [[READNONE_INTRINSIC]] // HAS_ERRNO: declare double @llvm.fabs.f64(double) [[READNONE_INTRINSIC]] // HAS_ERRNO: declare float @llvm.fabs.f32(float) [[READNONE_INTRINSIC]] // HAS_ERRNO: declare x86_fp80 @llvm.fabs.f80(x86_fp80) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare fp128 @llvm.fabs.f128(fp128) [[READNONE_INTRINSIC]] __builtin_frexp(f,i); __builtin_frexpf(f,i); __builtin_frexpl(f,i); @@ -51,14 +55,14 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) { // HAS_ERRNO: declare float @frexpf(float, i32*) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @frexpl(x86_fp80, i32*) [[NOT_READNONE]] - __builtin_huge_val(); __builtin_huge_valf(); __builtin_huge_vall(); + __builtin_huge_val(); __builtin_huge_valf(); __builtin_huge_vall(); __builtin_huge_valf128(); // NO__ERRNO-NOT: .huge // NO__ERRNO-NOT: @huge // HAS_ERRNO-NOT: .huge // HAS_ERRNO-NOT: @huge - __builtin_inf(); __builtin_inff(); __builtin_infl(); + __builtin_inf(); __builtin_inff(); __builtin_infl(); __builtin_inff128(); // NO__ERRNO-NOT: .inf // NO__ERRNO-NOT: @inf @@ -83,23 +87,27 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) { // HAS_ERRNO: declare float @modff(float, float*) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @modfl(x86_fp80, x86_fp80*) [[NOT_READNONE]] - __builtin_nan(c); __builtin_nanf(c); __builtin_nanl(c); + __builtin_nan(c); __builtin_nanf(c); __builtin_nanl(c); __builtin_nanf128(c); // NO__ERRNO: declare double @nan(i8*) [[READNONE]] // NO__ERRNO: declare float @nanf(i8*) [[READNONE]] // NO__ERRNO: declare x86_fp80 @nanl(i8*) [[READNONE]] +// NO__ERRNO: declare fp128 @nanf128(i8*) [[READNONE]] // HAS_ERRNO: declare double @nan(i8*) [[READNONE:#[0-9]+]] // HAS_ERRNO: declare float @nanf(i8*) [[READNONE]] // HAS_ERRNO: declare x86_fp80 @nanl(i8*) [[READNONE]] +// HAS_ERRNO: declare fp128 @nanf128(i8*) [[READNONE]] - __builtin_nans(c); __builtin_nansf(c); __builtin_nansl(c); + __builtin_nans(c); __builtin_nansf(c); __builtin_nansl(c); __builtin_nansf128(c); // NO__ERRNO: declare double @nans(i8*) [[READNONE]] // NO__ERRNO: declare float @nansf(i8*) [[READNONE]] // NO__ERRNO: declare x86_fp80 @nansl(i8*) [[READNONE]] +// NO__ERRNO: declare fp128 @nansf128(i8*) [[READNONE]] // HAS_ERRNO: declare double @nans(i8*) [[READNONE]] // HAS_ERRNO: declare float @nansf(i8*) [[READNONE]] // HAS_ERRNO: declare x86_fp80 @nansl(i8*) [[READNONE]] +// HAS_ERRNO: declare fp128 @nansf128(i8*) [[READNONE]] __builtin_pow(f,f); __builtin_powf(f,f); __builtin_powl(f,f); diff --git a/test/Sema/constant-builtins-2.c b/test/Sema/constant-builtins-2.c index a4baecb615..40cfce1f4a 100644 --- a/test/Sema/constant-builtins-2.c +++ b/test/Sema/constant-builtins-2.c @@ -5,24 +5,35 @@ double g0 = __builtin_huge_val(); float g1 = __builtin_huge_valf(); long double g2 = __builtin_huge_vall(); +#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__) +__float128 g2_2 = __builtin_huge_valf128(); +#endif double g3 = __builtin_inf(); float g4 = __builtin_inff(); long double g5 = __builtin_infl(); +#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__) +__float128 g5_2 = __builtin_inff128(); +#endif double g6 = __builtin_nan(""); float g7 = __builtin_nanf(""); long double g8 = __builtin_nanl(""); +#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__) +__float128 g8_2 = __builtin_nanf128(""); +#endif // GCC constant folds these too (via native strtol): //double g6_1 = __builtin_nan("1"); //float g7_1 = __builtin_nanf("1"); //long double g8_1 = __builtin_nanl("1"); -// APFloat doesn't have signalling NaN functions. -//double g9 = __builtin_nans(""); -//float g10 = __builtin_nansf(""); -//long double g11 = __builtin_nansl(""); +double g9 = __builtin_nans(""); +float g10 = __builtin_nansf(""); +long double g11 = __builtin_nansl(""); +#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__) +__float128 g11_2 = __builtin_nansf128(""); +#endif //int g12 = __builtin_abs(-12); @@ -32,10 +43,16 @@ double g13_1 = __builtin_fabs(-__builtin_inf()); float g14 = __builtin_fabsf(-12.f); // GCC doesn't eat this one. //long double g15 = __builtin_fabsfl(-12.0L); +#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__) +__float128 g15_2 = __builtin_fabsf128(-12.q); +#endif float g16 = __builtin_copysign(1.0, -1.0); double g17 = __builtin_copysignf(1.0f, -1.0f); long double g18 = __builtin_copysignl(1.0L, -1.0L); +#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__) +__float128 g18_2 = __builtin_copysignf128(1.0q, -1.0q); +#endif char classify_nan [__builtin_fpclassify(+1, -1, -1, -1, -1, __builtin_nan(""))]; char classify_snan [__builtin_fpclassify(+1, -1, -1, -1, -1, __builtin_nans(""))];