Commit 0c8d3c2b 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): 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.

From-SVN: r126725
parent 7faa1bbb
2007-07-18 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> 2007-07-18 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
PR target/30652 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.
2007-07-18 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
PR target/30652
PR middle-end/20558 PR middle-end/20558
* builtins.c (expand_builtin_interclass_mathfn): Provide a * builtins.c (expand_builtin_interclass_mathfn): Provide a
......
...@@ -2211,8 +2211,8 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget) ...@@ -2211,8 +2211,8 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget)
static rtx static rtx
expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget) expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget)
{ {
optab builtin_optab; optab builtin_optab = 0;
enum insn_code icode; enum insn_code icode = CODE_FOR_nothing;
rtx op0; rtx op0;
tree fndecl = get_callee_fndecl (exp); tree fndecl = get_callee_fndecl (exp);
enum machine_mode mode; enum machine_mode mode;
...@@ -2230,6 +2230,10 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget) ...@@ -2230,6 +2230,10 @@ 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_ISFINITE:
CASE_FLT_FN (BUILT_IN_FINITE):
/* These builtins have no optabs (yet). */
break;
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
...@@ -2241,7 +2245,8 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget) ...@@ -2241,7 +2245,8 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget)
/* Optab mode depends on the mode of the input argument. */ /* Optab mode depends on the mode of the input argument. */
mode = TYPE_MODE (TREE_TYPE (arg)); 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. */ /* Before working hard, check whether the instruction is available. */
if (icode != CODE_FOR_nothing) if (icode != CODE_FOR_nothing)
...@@ -2295,6 +2300,22 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget) ...@@ -2295,6 +2300,22 @@ 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_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: default:
break; break;
} }
...@@ -6150,6 +6171,8 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, ...@@ -6150,6 +6171,8 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
if (! flag_unsafe_math_optimizations) if (! flag_unsafe_math_optimizations)
break; break;
CASE_FLT_FN (BUILT_IN_ISINF): CASE_FLT_FN (BUILT_IN_ISINF):
CASE_FLT_FN (BUILT_IN_FINITE):
case BUILT_IN_ISFINITE:
target = expand_builtin_interclass_mathfn (exp, target, subtarget); target = expand_builtin_interclass_mathfn (exp, target, subtarget);
if (target) if (target)
return target; return target;
...@@ -9569,7 +9592,7 @@ fold_builtin_classify (tree fndecl, tree arg, int builtin_index) ...@@ -9569,7 +9592,7 @@ fold_builtin_classify (tree fndecl, tree arg, int builtin_index)
return NULL_TREE; return NULL_TREE;
case BUILT_IN_FINITE: case BUILT_IN_ISFINITE:
if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg))) if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg)))
&& !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg)))) && !HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg))))
return omit_one_operand (type, integer_one_node, arg); return omit_one_operand (type, integer_one_node, arg);
...@@ -9972,7 +9995,8 @@ fold_builtin_1 (tree fndecl, tree arg0, bool ignore) ...@@ -9972,7 +9995,8 @@ fold_builtin_1 (tree fndecl, tree arg0, bool ignore)
case BUILT_IN_FINITED32: case BUILT_IN_FINITED32:
case BUILT_IN_FINITED64: case BUILT_IN_FINITED64:
case BUILT_IN_FINITED128: 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_FLT_FN (BUILT_IN_ISINF):
case BUILT_IN_ISINFD32: case BUILT_IN_ISINFD32:
......
...@@ -654,6 +654,7 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITEL, "finitel", BT_FN_INT_LONGDOUBLE, ATTR_ ...@@ -654,6 +654,7 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITEL, "finitel", BT_FN_INT_LONGDOUBLE, ATTR_
DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITED32, "finited32", BT_FN_INT_DFLOAT32, ATTR_CONST_NOTHROW_LIST) 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_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_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_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_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) DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFL, "isinfl", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST)
......
...@@ -5437,6 +5437,7 @@ should be called and the @var{flag} argument passed to it. ...@@ -5437,6 +5437,7 @@ should be called and the @var{flag} argument passed to it.
@node Other Builtins @node Other Builtins
@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_isgreater @findex __builtin_isgreater
@findex __builtin_isgreaterequal @findex __builtin_isgreaterequal
@findex __builtin_isless @findex __builtin_isless
...@@ -5965,6 +5966,8 @@ the same names as the standard macros ( @code{isgreater}, ...@@ -5965,6 +5966,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
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})
......
...@@ -3,6 +3,11 @@ ...@@ -3,6 +3,11 @@
* 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.
2007-07-18 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* gcc.dg/pr28796-1.c: Add more cases.
* gcc.dg/pr28796-2.c: Likewise.
2007-07-17 Janus Weil <jaydub66@gmail.com> 2007-07-17 Janus Weil <jaydub66@gmail.com>
PR fortran/32535 PR fortran/32535
...@@ -38,6 +38,20 @@ int main() ...@@ -38,6 +38,20 @@ int main()
if (__builtin_finitel (ld) != 1) if (__builtin_finitel (ld) != 1)
link_error (); 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) if (f != f)
link_error (); link_error ();
if (d != d) if (d != d)
......
...@@ -43,10 +43,23 @@ foo_1 (float f, double d, long double ld, ...@@ -43,10 +43,23 @@ 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_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) if (__builtin_finite (f) != res_isfin)
abort (); abort ();
if (__builtin_finite (d) != res_isfin) if (__builtin_finite (d) != res_isfin)
abort (); abort ();
if (__builtin_finitel (d) != res_isfin)
abort ();
if (__builtin_finitel (ld) != res_isfin)
abort ();
} }
void __attribute__ ((__noinline__)) void __attribute__ ((__noinline__))
......
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