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 "finite" 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/msg01211.html
> >
> > This one also generates correct (but slightly suboptimal) code for floats.
> > It also will be fixed with my type-generic builtins patch. But this one
> > can be installed now.
>
> isfinite should be DEF_C99_C90RES_BUILTIN (or DEF_C99_BUILTIN,
> I don't have C90 handy to check if it is a reserved keyword there). Also
> "I'll resubmit with documenation for the new
> builtin. (I wasn't sure which doc section to put it in right now.)"
> Builtins are documented in extend.texi.
>
> Same concerns on optimize_size and soft-fp targets.
>
> Please re-post with the changes above (after checking C90).
By "doc section" back then I meant whether it should go in the C99 or
gcc-internal section. This was determined by whether I used DEF_GCC or
DEF_C99. Since Joseph later clarified DEF_GCC, that's what I went with.
This version adds documentation in extend.texi, and updates the attributes
in builtins.def to use "type generic".
Ok for mainline?
Thanks,
--Kaveh
2007-06-17 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
PR target/30652
* builtins.c (expand_builtin_interclass_mathfn): Allow for missing
optabs infrastructure. Provide generic implementation for
FINITE/ISFINITE.
(expand_builtin): Handle FINITE/ISFINITE.
(fold_builtin_classify): Make ISFINITE canonical instead of FINITE.
(fold_builtin_1): Likewise.
* builtins.def (BUILT_IN_ISFINITE): New.
* doc/extend.texi: Document isfinite.
testsuite:
* gcc.dg/pr28796-1.c: Add more cases.
* gcc.dg/pr28796-2.c: Likewise.
diff -rup orig/egcc-SVN20070708/gcc/builtins.c egcc-SVN20070708/gcc/builtins.c
--- orig/egcc-SVN20070708/gcc/builtins.c 2007-07-08 18:22:18.952003494 -0400
+++ egcc-SVN20070708/gcc/builtins.c 2007-07-08 19:00:55.371157749 -0400
@@ -2208,8 +2208,8 @@ expand_builtin_mathfn_3 (tree exp, rtx t
static rtx
expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget)
{
- optab builtin_optab;
- enum insn_code icode;
+ optab builtin_optab = 0;
+ enum insn_code icode = CODE_FOR_nothing;
rtx op0;
tree fndecl = get_callee_fndecl (exp);
enum machine_mode mode;
@@ -2227,6 +2227,10 @@ 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_ISFINITE:
+ CASE_FLT_FN (BUILT_IN_FINITE):
+ /* These builtins have no optabs (yet). */
+ break;
default:
gcc_unreachable ();
}
@@ -2238,7 +2242,8 @@ expand_builtin_interclass_mathfn (tree e
/* Optab mode depends on the mode of the input argument. */
mode = TYPE_MODE (TREE_TYPE (arg));
- icode = builtin_optab->handlers[(int) mode].insn_code;
+ if (builtin_optab)
+ icode = builtin_optab->handlers[(int) mode].insn_code;
/* Before working hard, check whether the instruction is available. */
if (icode != CODE_FOR_nothing)
@@ -2292,6 +2297,22 @@ expand_builtin_interclass_mathfn (tree e
build_real (type, r));
return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
}
+ CASE_FLT_FN (BUILT_IN_FINITE):
+ case BUILT_IN_ISFINITE:
+ {
+ /* isfinite(x) -> islessequal(fabs(x),DBL_MAX). */
+ tree const isle_fn = built_in_decls[BUILT_IN_ISLESSEQUAL];
+ tree const type = TREE_TYPE (arg);
+ REAL_VALUE_TYPE r;
+ char buf[128];
+
+ get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
+ real_from_string (&r, buf);
+ result = build_call_expr (isle_fn, 2,
+ fold_build1 (ABS_EXPR, type, arg),
+ build_real (type, r));
+ return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
+ }
default:
break;
}
@@ -6076,6 +6097,8 @@ expand_builtin (tree exp, rtx target, rt
if (! flag_unsafe_math_optimizations)
break;
CASE_FLT_FN (BUILT_IN_ISINF):
+ CASE_FLT_FN (BUILT_IN_FINITE):
+ case BUILT_IN_ISFINITE:
target = expand_builtin_interclass_mathfn (exp, target, subtarget);
if (target)
return target;
@@ -9489,7 +9512,7 @@ fold_builtin_classify (tree fndecl, tree
return NULL_TREE;
- case BUILT_IN_FINITE:
+ case BUILT_IN_ISFINITE:
if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg)))
&& !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
return omit_one_operand (type, integer_one_node, arg);
@@ -9892,7 +9915,8 @@ fold_builtin_1 (tree fndecl, tree arg0,
case BUILT_IN_FINITED32:
case BUILT_IN_FINITED64:
case BUILT_IN_FINITED128:
- return fold_builtin_classify (fndecl, arg0, BUILT_IN_FINITE);
+ case BUILT_IN_ISFINITE:
+ return fold_builtin_classify (fndecl, arg0, BUILT_IN_ISFINITE);
CASE_FLT_FN (BUILT_IN_ISINF):
case BUILT_IN_ISINFD32:
diff -rup orig/egcc-SVN20070708/gcc/builtins.def egcc-SVN20070708/gcc/builtins.def
--- orig/egcc-SVN20070708/gcc/builtins.def 2007-07-08 18:19:28.832254779 -0400
+++ egcc-SVN20070708/gcc/builtins.def 2007-07-08 19:00:55.373958219 -0400
@@ -653,6 +653,7 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITEL
DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITED32, "finited32", BT_FN_INT_DFLOAT32, ATTR_CONST_NOTHROW_LIST)
DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITED64, "finited64", BT_FN_INT_DFLOAT64, ATTR_CONST_NOTHROW_LIST)
DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITED128, "finited128", BT_FN_INT_DFLOAT128, ATTR_CONST_NOTHROW_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_ISFINITE, "isfinite", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC)
DEF_C99_C90RES_BUILTIN (BUILT_IN_ISINF, "isinf", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC)
DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFF, "isinff", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LIST)
DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFL, "isinfl", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST)
diff -rup orig/egcc-SVN20070708/gcc/doc/extend.texi egcc-SVN20070708/gcc/doc/extend.texi
--- orig/egcc-SVN20070708/gcc/doc/extend.texi 2007-07-03 11:26:10.000000000 -0400
+++ egcc-SVN20070708/gcc/doc/extend.texi 2007-07-08 19:13:06.906457015 -0400
@@ -5412,6 +5412,7 @@ should be called and the @var{flag} argu
@node Other Builtins
@section Other built-in functions provided by GCC
@cindex built-in functions
+@findex __builtin_isfinite
@findex __builtin_isgreater
@findex __builtin_isgreaterequal
@findex __builtin_isless
@@ -5940,6 +5941,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.
@deftypefn {Built-in Function} int __builtin_types_compatible_p (@var{type1}, @var{type2})
diff -rup orig/egcc-SVN20070708/gcc/testsuite/gcc.dg/pr28796-1.c egcc-SVN20070708/gcc/testsuite/gcc.dg/pr28796-1.c
--- orig/egcc-SVN20070708/gcc/testsuite/gcc.dg/pr28796-1.c 2007-07-08 18:22:18.962058143 -0400
+++ egcc-SVN20070708/gcc/testsuite/gcc.dg/pr28796-1.c 2007-07-08 19:00:55.374776917 -0400
@@ -38,6 +38,20 @@ int main()
if (__builtin_finitel (ld) != 1)
link_error ();
+ if (__builtin_isinf (f) != 0)
+ link_error ();
+ if (__builtin_isinf (d) != 0)
+ link_error ();
+ if (__builtin_isinf (ld) != 0)
+ link_error ();
+
+ if (__builtin_isfinite (f) != 1)
+ link_error ();
+ if (__builtin_isfinite (d) != 1)
+ link_error ();
+ if (__builtin_isfinite (ld) != 1)
+ link_error ();
+
if (f != f)
link_error ();
if (d != d)
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 18:22:18.962891723 -0400
+++ egcc-SVN20070708/gcc/testsuite/gcc.dg/pr28796-2.c 2007-07-08 19:00:55.375472714 -0400
@@ -43,10 +43,23 @@ foo_1 (float f, double d, long double ld
if (__builtin_isinfl (ld) != res_isinf)
abort ();
+ if (__builtin_isfinite (f) != res_isfin)
+ abort ();
+ if (__builtin_isfinite (d) != res_isfin)
+ abort ();
+ if (__builtin_isfinite (ld) != res_isfin)
+ abort ();
+
+ if (__builtin_finitef (f) != res_isfin)
+ abort ();
if (__builtin_finite (f) != res_isfin)
abort ();
if (__builtin_finite (d) != res_isfin)
abort ();
+ if (__builtin_finitel (d) != res_isfin)
+ abort ();
+ if (__builtin_finitel (ld) != res_isfin)
+ abort ();
}
void __attribute__ ((__noinline__))