This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]