This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch, fortran] Fix NEAREST for float formats without infinity
- From: "Ulrich Weigand" <uweigand at de dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org, fortran at gcc dot gnu dot org
- Date: Wed, 25 Mar 2009 21:32:45 +0100 (CET)
- Subject: [patch, fortran] Fix NEAREST for float formats without infinity
Hello,
gfc_conv_intrinsic_nearest currently uses the "__builtin_inf" family
of intrinsics. This is a problem for platforms with floating-point
formats that do not support infinity, like single-precision float
on the SPU.
In this situation, fold_builtin_inf will issue a warning "target
format does not support infinity". This may be appropriate for
explicit uses of the INFINITY macro in C code -- but in fact you
also get the same warning today whenever you use NEAREST on a
REAL (4) type in Fortran on the SPU; this seems quite confusing.
I suggest to use __builtin_huge_val instead of __builtin_inf to
implement NEAREST. The implementation of the two is completely
equivalent -- except that __builtin_huge_val does not issue the
warning. The following patch implements this change.
Tested on spu-elf with no regressions. Fixes a number of test
cases that failed due to the warning on NEAREST.
OK for mainline?
Bye,
Ulrich
ChangeLog:
* f95-lang.c (gfc_init_builtin_functions): Define BUILT_IN_HUGE_VAL
family of intrinsics instead of BUILT_IN_INF family.
* trans-intrinsics.c (gfc_conv_intrinsic_nearest): Use
BUILT_IN_HUGE_VAL instead of BUILT_IN_INF.
Index: gcc/fortran/f95-lang.c
===================================================================
*** gcc/fortran/f95-lang.c (revision 144779)
--- gcc/fortran/f95-lang.c (working copy)
*************** gfc_init_builtin_functions (void)
*** 917,928 ****
gfc_define_builtin ("__builtin_fmodf", mfunc_float[1],
BUILT_IN_FMODF, "fmodf", true);
! gfc_define_builtin ("__builtin_infl", mfunc_longdouble[3],
! BUILT_IN_INFL, "__builtin_infl", true);
! gfc_define_builtin ("__builtin_inf", mfunc_double[3],
! BUILT_IN_INF, "__builtin_inf", true);
! gfc_define_builtin ("__builtin_inff", mfunc_float[3],
! BUILT_IN_INFF, "__builtin_inff", true);
/* lround{f,,l} and llround{f,,l} */
type = tree_cons (NULL_TREE, float_type_node, void_list_node);
--- 917,928 ----
gfc_define_builtin ("__builtin_fmodf", mfunc_float[1],
BUILT_IN_FMODF, "fmodf", true);
! gfc_define_builtin ("__builtin_huge_vall", mfunc_longdouble[3],
! BUILT_IN_HUGE_VALL, "__builtin_huge_vall", true);
! gfc_define_builtin ("__builtin_huge_val", mfunc_double[3],
! BUILT_IN_HUGE_VAL, "__builtin_huge_val", true);
! gfc_define_builtin ("__builtin_huge_valf", mfunc_float[3],
! BUILT_IN_HUGE_VALF, "__builtin_huge_valf", true);
/* lround{f,,l} and llround{f,,l} */
type = tree_cons (NULL_TREE, float_type_node, void_list_node);
Index: gcc/fortran/trans-intrinsic.c
===================================================================
*** gcc/fortran/trans-intrinsic.c (revision 144779)
--- gcc/fortran/trans-intrinsic.c (working copy)
*************** gfc_conv_intrinsic_fraction (gfc_se * se
*** 3129,3160 ****
/* NEAREST (s, dir) is translated into
! tmp = copysign (INF, dir);
return nextafter (s, tmp);
*/
static void
gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
{
tree args[2], type, tmp;
! int nextafter, copysign, inf;
switch (expr->ts.kind)
{
case 4:
nextafter = BUILT_IN_NEXTAFTERF;
copysign = BUILT_IN_COPYSIGNF;
! inf = BUILT_IN_INFF;
break;
case 8:
nextafter = BUILT_IN_NEXTAFTER;
copysign = BUILT_IN_COPYSIGN;
! inf = BUILT_IN_INF;
break;
case 10:
case 16:
nextafter = BUILT_IN_NEXTAFTERL;
copysign = BUILT_IN_COPYSIGNL;
! inf = BUILT_IN_INFL;
break;
default:
gcc_unreachable ();
--- 3129,3160 ----
/* NEAREST (s, dir) is translated into
! tmp = copysign (HUGE_VAL, dir);
return nextafter (s, tmp);
*/
static void
gfc_conv_intrinsic_nearest (gfc_se * se, gfc_expr * expr)
{
tree args[2], type, tmp;
! int nextafter, copysign, huge_val;
switch (expr->ts.kind)
{
case 4:
nextafter = BUILT_IN_NEXTAFTERF;
copysign = BUILT_IN_COPYSIGNF;
! huge_val = BUILT_IN_HUGE_VALF;
break;
case 8:
nextafter = BUILT_IN_NEXTAFTER;
copysign = BUILT_IN_COPYSIGN;
! huge_val = BUILT_IN_HUGE_VAL;
break;
case 10:
case 16:
nextafter = BUILT_IN_NEXTAFTERL;
copysign = BUILT_IN_COPYSIGNL;
! huge_val = BUILT_IN_HUGE_VALL;
break;
default:
gcc_unreachable ();
*************** gfc_conv_intrinsic_nearest (gfc_se * se,
*** 3163,3169 ****
type = gfc_typenode_for_spec (&expr->ts);
gfc_conv_intrinsic_function_args (se, expr, args, 2);
tmp = build_call_expr (built_in_decls[copysign], 2,
! build_call_expr (built_in_decls[inf], 0),
fold_convert (type, args[1]));
se->expr = build_call_expr (built_in_decls[nextafter], 2,
fold_convert (type, args[0]), tmp);
--- 3163,3169 ----
type = gfc_typenode_for_spec (&expr->ts);
gfc_conv_intrinsic_function_args (se, expr, args, 2);
tmp = build_call_expr (built_in_decls[copysign], 2,
! build_call_expr (built_in_decls[huge_val], 0),
fold_convert (type, args[1]));
se->expr = build_call_expr (built_in_decls[nextafter], 2,
fold_convert (type, args[0]), tmp);
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com