From: Kaveh R. Ghazi Date: Wed, 18 Jul 2007 17:51:13 +0000 (+0000) Subject: re PR target/30652 (SSE expansion is missing for isinf() and other fpclassify functions) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8a91c45bbfb3d5c99560ab89dc1dc55a1add8719;p=gcc.git re PR target/30652 (SSE expansion is missing for isinf() and other fpclassify functions) PR target/30652 * builtins.c (expand_builtin_interclass_mathfn): Provide a generic transformation for builtin ISNORMAL. (expand_builtin): Handle BUILT_IN_ISNORMAL. * builtins.def (BUILT_IN_ISNORMAL): New. * doc/extend.texi: Document isnormal. testsuite: * gcc.dg/pr28796-2.c: Add more cases. From-SVN: r126726 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3bd353f19b5..24b7c2e91e1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2007-07-18 Kaveh R. Ghazi + + PR target/30652 + + * builtins.c (expand_builtin_interclass_mathfn): Provide a generic + transformation for builtin ISNORMAL. + (expand_builtin): Handle BUILT_IN_ISNORMAL. + * builtins.def (BUILT_IN_ISNORMAL): New. + * doc/extend.texi: Document isnormal. + 2007-07-18 Kaveh R. Ghazi PR target/30652 diff --git a/gcc/builtins.c b/gcc/builtins.c index b96cfb24da1..d0e5db903bc 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -2230,6 +2230,7 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget) errno_set = true; builtin_optab = ilogb_optab; break; CASE_FLT_FN (BUILT_IN_ISINF): builtin_optab = isinf_optab; break; + case BUILT_IN_ISNORMAL: case BUILT_IN_ISFINITE: CASE_FLT_FN (BUILT_IN_FINITE): /* These builtins have no optabs (yet). */ @@ -2316,6 +2317,28 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget) build_real (type, r)); return expand_expr (result, target, VOIDmode, EXPAND_NORMAL); } + case BUILT_IN_ISNORMAL: + { + /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) & + islessequal(fabs(x),DBL_MAX). */ + tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL]; + tree const isge_fn = built_in_decls[BUILT_IN_ISGREATEREQUAL]; + tree const type = TREE_TYPE (arg); + REAL_VALUE_TYPE rmax, rmin; + char buf[128]; + + get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf)); + real_from_string (&rmax, buf); + sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (mode)->emin - 1); + real_from_string (&rmin, buf); + arg = builtin_save_expr (fold_build1 (ABS_EXPR, type, arg)); + result = build_call_expr (isle_fn, 2, arg, + build_real (type, rmax)); + result = fold_build2 (BIT_AND_EXPR, integer_type_node, result, + build_call_expr (isge_fn, 2, arg, + build_real (type, rmin))); + return expand_expr (result, target, VOIDmode, EXPAND_NORMAL); + } default: break; } @@ -6173,6 +6196,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, CASE_FLT_FN (BUILT_IN_ISINF): CASE_FLT_FN (BUILT_IN_FINITE): case BUILT_IN_ISFINITE: + case BUILT_IN_ISNORMAL: target = expand_builtin_interclass_mathfn (exp, target, subtarget); if (target) return target; diff --git a/gcc/builtins.def b/gcc/builtins.def index 8f5f4f24cb8..2f23d870bbf 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -667,6 +667,7 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNANL, "isnanl", BT_FN_INT_LONGDOUBLE, ATTR_CO DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNAND32, "isnand32", BT_FN_INT_DFLOAT32, ATTR_CONST_NOTHROW_LIST) DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNAND64, "isnand64", BT_FN_INT_DFLOAT64, ATTR_CONST_NOTHROW_LIST) DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNAND128, "isnand128", BT_FN_INT_DFLOAT128, ATTR_CONST_NOTHROW_LIST) +DEF_GCC_BUILTIN (BUILT_IN_ISNORMAL, "isnormal", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC) DEF_GCC_BUILTIN (BUILT_IN_ISGREATER, "isgreater", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC) DEF_GCC_BUILTIN (BUILT_IN_ISGREATEREQUAL, "isgreaterequal", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC) DEF_GCC_BUILTIN (BUILT_IN_ISLESS, "isless", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index c974d5206cc..5c74b840131 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -5438,6 +5438,7 @@ should be called and the @var{flag} argument passed to it. @section Other built-in functions provided by GCC @cindex built-in functions @findex __builtin_isfinite +@findex __builtin_isnormal @findex __builtin_isgreater @findex __builtin_isgreaterequal @findex __builtin_isless @@ -5966,8 +5967,8 @@ the same names as the standard macros ( @code{isgreater}, @code{islessgreater}, and @code{isunordered}) , with @code{__builtin_} prefixed. We intend for a library implementor to be able to simply @code{#define} each standard macro to its built-in equivalent. -In the same fashion, GCC provides an @code{isfinite} built-in used -with @code{__builtin_} prefixed. +In the same fashion, GCC provides @code{isfinite} and @code{isnormal} +built-ins used with @code{__builtin_} prefixed. @deftypefn {Built-in Function} int __builtin_types_compatible_p (@var{type1}, @var{type2}) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 64a5d01f4d0..ab18376ccf3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2007-07-18 Kaveh R. Ghazi + + * gcc.dg/pr28796-2.c: Add more cases. + 2007-07-18 Kaveh R. Ghazi * gcc.dg/pr28796-1.c: Add more cases. diff --git a/gcc/testsuite/gcc.dg/pr28796-2.c b/gcc/testsuite/gcc.dg/pr28796-2.c index 6f929a81fd6..c69a60e0c4a 100644 --- a/gcc/testsuite/gcc.dg/pr28796-2.c +++ b/gcc/testsuite/gcc.dg/pr28796-2.c @@ -6,7 +6,8 @@ extern void abort (void); void __attribute__ ((__noinline__)) foo_1 (float f, double d, long double ld, - int res_unord, int res_isnan, int res_isinf, int res_isfin) + int res_unord, int res_isnan, int res_isinf, + int res_isfin, int res_isnorm) { if (__builtin_isunordered (f, 0) != res_unord) abort (); @@ -43,6 +44,13 @@ foo_1 (float f, double d, long double ld, if (__builtin_isinfl (ld) != res_isinf) abort (); + if (__builtin_isnormal (f) != res_isnorm) + abort (); + if (__builtin_isnormal (d) != res_isnorm) + abort (); + if (__builtin_isnormal (ld) != res_isnorm) + abort (); + if (__builtin_isfinite (f) != res_isfin) abort (); if (__builtin_isfinite (d) != res_isfin) @@ -64,10 +72,12 @@ foo_1 (float f, double d, long double ld, void __attribute__ ((__noinline__)) foo (float f, double d, long double ld, - int res_unord, int res_isnan, int res_isinf, int res_isfin) + int res_unord, int res_isnan, int res_isinf, + int res_isfin, int res_isnorm) { - foo_1 (f, d, ld, res_unord, res_isnan, res_isinf, res_isfin); - foo_1 (-f, -d, -ld, res_unord, res_isnan, res_isinf, res_isfin); + foo_1 (f, d, ld, res_unord, res_isnan, res_isinf, res_isfin, res_isnorm); + /* Try all values negative as well. */ + foo_1 (-f, -d, -ld, res_unord, res_isnan, res_isinf, res_isfin, res_isnorm); } int main() @@ -77,19 +87,28 @@ int main() long double ld; f = __builtin_nanf(""); d = __builtin_nan(""); ld = __builtin_nanl(""); - foo(f, d, ld, /*unord=*/ 1, /*isnan=*/ 1, /*isinf=*/ 0, /*isfin=*/ 0); + foo(f, d, ld, /*unord=*/ 1, /*isnan=*/ 1, /*isinf=*/ 0, /*isfin=*/ 0, /*isnorm=*/ 0); f = __builtin_inff(); d = __builtin_inf(); ld = __builtin_infl(); - foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 1, /*isfin=*/ 0); + foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 1, /*isfin=*/ 0, /*isnorm=*/ 0); f = 0; d = 0; ld = 0; - foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1); + foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 0); + + f = 1; d = 1; ld = 1; + foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 1); f = __FLT_MIN__; d = __DBL_MIN__; ld = __LDBL_MIN__; - foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1); + foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 1); + + f = __FLT_MIN__/2; d = __DBL_MIN__/2; ld = __LDBL_MIN__/2; + foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 0); f = __FLT_MAX__; d = __DBL_MAX__; ld = __LDBL_MAX__; - foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1); + foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1, /*isnorm=*/ 1); + + f = __FLT_MAX__*2; d = __DBL_MAX__*2; ld = __LDBL_MAX__*2; + foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 1, /*isfin=*/ 0, /*isnorm=*/ 0); return 0; }