Commit 8a91c45b by Kaveh R. Ghazi Committed by Kaveh Ghazi

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
parent 0c8d3c2b
...@@ -2,6 +2,16 @@ ...@@ -2,6 +2,16 @@
PR target/30652 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 <ghazi@caip.rutgers.edu>
PR target/30652
* builtins.c (expand_builtin_interclass_mathfn): Allow for missing * builtins.c (expand_builtin_interclass_mathfn): Allow for missing
optabs infrastructure. Provide generic implementation for optabs infrastructure. Provide generic implementation for
FINITE/ISFINITE. FINITE/ISFINITE.
......
...@@ -2230,6 +2230,7 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget) ...@@ -2230,6 +2230,7 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget)
errno_set = true; builtin_optab = ilogb_optab; break; errno_set = true; builtin_optab = ilogb_optab; break;
CASE_FLT_FN (BUILT_IN_ISINF): CASE_FLT_FN (BUILT_IN_ISINF):
builtin_optab = isinf_optab; break; builtin_optab = isinf_optab; break;
case BUILT_IN_ISNORMAL:
case BUILT_IN_ISFINITE: case BUILT_IN_ISFINITE:
CASE_FLT_FN (BUILT_IN_FINITE): CASE_FLT_FN (BUILT_IN_FINITE):
/* These builtins have no optabs (yet). */ /* These builtins have no optabs (yet). */
...@@ -2316,6 +2317,28 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget) ...@@ -2316,6 +2317,28 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget)
build_real (type, r)); build_real (type, r));
return expand_expr (result, target, VOIDmode, EXPAND_NORMAL); 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: default:
break; break;
} }
...@@ -6173,6 +6196,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, ...@@ -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_ISINF):
CASE_FLT_FN (BUILT_IN_FINITE): CASE_FLT_FN (BUILT_IN_FINITE):
case BUILT_IN_ISFINITE: case BUILT_IN_ISFINITE:
case BUILT_IN_ISNORMAL:
target = expand_builtin_interclass_mathfn (exp, target, subtarget); target = expand_builtin_interclass_mathfn (exp, target, subtarget);
if (target) if (target)
return target; return target;
......
...@@ -667,6 +667,7 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNANL, "isnanl", BT_FN_INT_LONGDOUBLE, ATTR_CO ...@@ -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_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_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_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_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_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) DEF_GCC_BUILTIN (BUILT_IN_ISLESS, "isless", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC)
......
...@@ -5438,6 +5438,7 @@ should be called and the @var{flag} argument passed to it. ...@@ -5438,6 +5438,7 @@ should be called and the @var{flag} argument passed to it.
@section Other built-in functions provided by GCC @section Other built-in functions provided by GCC
@cindex built-in functions @cindex built-in functions
@findex __builtin_isfinite @findex __builtin_isfinite
@findex __builtin_isnormal
@findex __builtin_isgreater @findex __builtin_isgreater
@findex __builtin_isgreaterequal @findex __builtin_isgreaterequal
@findex __builtin_isless @findex __builtin_isless
...@@ -5966,8 +5967,8 @@ the same names as the standard macros ( @code{isgreater}, ...@@ -5966,8 +5967,8 @@ the same names as the standard macros ( @code{isgreater},
@code{islessgreater}, and @code{isunordered}) , with @code{__builtin_} @code{islessgreater}, and @code{isunordered}) , with @code{__builtin_}
prefixed. We intend for a library implementor to be able to simply prefixed. We intend for a library implementor to be able to simply
@code{#define} each standard macro to its built-in equivalent. @code{#define} each standard macro to its built-in equivalent.
In the same fashion, GCC provides an @code{isfinite} built-in used In the same fashion, GCC provides @code{isfinite} and @code{isnormal}
with @code{__builtin_} prefixed. built-ins used with @code{__builtin_} prefixed.
@deftypefn {Built-in Function} int __builtin_types_compatible_p (@var{type1}, @var{type2}) @deftypefn {Built-in Function} int __builtin_types_compatible_p (@var{type1}, @var{type2})
......
2007-07-18 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> 2007-07-18 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* gcc.dg/pr28796-2.c: Add more cases.
2007-07-18 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* gcc.dg/pr28796-1.c: Add more cases. * gcc.dg/pr28796-1.c: Add more cases.
* gcc.dg/pr28796-2.c: Likewise. * gcc.dg/pr28796-2.c: Likewise.
...@@ -6,7 +6,8 @@ extern void abort (void); ...@@ -6,7 +6,8 @@ extern void abort (void);
void __attribute__ ((__noinline__)) void __attribute__ ((__noinline__))
foo_1 (float f, double d, long double ld, 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) if (__builtin_isunordered (f, 0) != res_unord)
abort (); abort ();
...@@ -43,6 +44,13 @@ foo_1 (float f, double d, long double ld, ...@@ -43,6 +44,13 @@ foo_1 (float f, double d, long double ld,
if (__builtin_isinfl (ld) != res_isinf) if (__builtin_isinfl (ld) != res_isinf)
abort (); 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) if (__builtin_isfinite (f) != res_isfin)
abort (); abort ();
if (__builtin_isfinite (d) != res_isfin) if (__builtin_isfinite (d) != res_isfin)
...@@ -64,10 +72,12 @@ foo_1 (float f, double d, long double ld, ...@@ -64,10 +72,12 @@ foo_1 (float f, double d, long double ld,
void __attribute__ ((__noinline__)) void __attribute__ ((__noinline__))
foo (float f, double d, long double ld, 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, res_isnorm);
foo_1 (-f, -d, -ld, res_unord, res_isnan, res_isinf, res_isfin); /* Try all values negative as well. */
foo_1 (-f, -d, -ld, res_unord, res_isnan, res_isinf, res_isfin, res_isnorm);
} }
int main() int main()
...@@ -77,19 +87,28 @@ int main() ...@@ -77,19 +87,28 @@ int main()
long double ld; long double ld;
f = __builtin_nanf(""); d = __builtin_nan(""); ld = __builtin_nanl(""); 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(); 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; 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__; 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__; 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; return 0;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment