This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH PING]: middle-end: provide generic "isnormal" transformation
On Sun, 8 Jul 2007, Richard Guenther wrote:
> On 7/8/07, Kaveh R. GHAZI <ghazi@caip.rutgers.edu> wrote:
> > PING.
> >
> > http://gcc.gnu.org/ml/gcc-patches/2007-06/msg01292.html
> >
> > This patch WILL generate incorrect code for certain subnormal numbers.
> > However that problem is fixed by my "type generic" builtins patch here:
> > http://gcc.gnu.org/ml/gcc-patches/2007-07/msg00691.html
> >
> > There's nothing wrong with this patch per se, so it can be reviewed now
> > with the understanding that I'll apply it after the fix above and switch
> > it's attributes to include "type generic".
>
> Same as for the other. The builtin should be C99_C90RES (if it is reserved
> by C90). I'm not sure why all of the comparison ones are not - Joseph?
>
> Otherwise ok with documentation in extend.texi.
Here is the "isnormal" patch updated with documentation and attribute
"type generic". Left it as DEF_GCC as per other messages.
Ok for mainline?
Thanks,
--Kaveh
2007-06-18 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
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.
diff -rup orig/egcc-SVN20070708/gcc/builtins.c egcc-SVN20070708/gcc/builtins.c
--- orig/egcc-SVN20070708/gcc/builtins.c 2007-07-08 20:13:53.690740803 -0400
+++ egcc-SVN20070708/gcc/builtins.c 2007-07-08 19:36:43.136788057 -0400
@@ -2227,6 +2227,7 @@ expand_builtin_interclass_mathfn (tree e
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). */
@@ -2313,6 +2314,28 @@ expand_builtin_interclass_mathfn (tree e
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;
}
@@ -6099,6 +6122,7 @@ expand_builtin (tree exp, rtx target, rt
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 -rup orig/egcc-SVN20070708/gcc/builtins.def egcc-SVN20070708/gcc/builtins.def
--- orig/egcc-SVN20070708/gcc/builtins.def 2007-07-08 20:13:53.693522390 -0400
+++ egcc-SVN20070708/gcc/builtins.def 2007-07-08 19:36:43.139612931 -0400
@@ -666,6 +666,7 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNANL,
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 -rup orig/egcc-SVN20070708/gcc/doc/extend.texi egcc-SVN20070708/gcc/doc/extend.texi
--- orig/egcc-SVN20070708/gcc/doc/extend.texi 2007-07-08 19:35:57.433477485 -0400
+++ egcc-SVN20070708/gcc/doc/extend.texi 2007-07-08 19:38:54.875433184 -0400
@@ -5413,6 +5413,7 @@ should be called and the @var{flag} argu
@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
@@ -5941,8 +5942,8 @@ the same names as the standard macros (
@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 -rup orig/egcc-SVN20070708/gcc/testsuite/gcc.dg/pr28796-2.c egcc-SVN20070708/gcc/testsuite/gcc.dg/pr28796-2.c
--- orig/egcc-SVN20070708/gcc/testsuite/gcc.dg/pr28796-2.c 2007-07-08 20:13:53.694807406 -0400
+++ egcc-SVN20070708/gcc/testsuite/gcc.dg/pr28796-2.c 2007-07-08 19:36:43.140881784 -0400
@@ -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;
}