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]

[Committed] C99 unordered comparisons are polymorphic builtins


The following patch simply moves more code from c-common.c's function
expand_unordered_cmp to builtins.c's fold_builtin_unordered_cmp.  In
my first attempt to move this functionality, I thought that the front
ends were doing far more work type checking than they needed to.  It
was only when I tried testing a patch to delete expand_unordered_cmp
that I understood why.

The C99 unordered comparison functions aren't regular functions at all,
but are allowed to be macros.  The C99 isgreater function can accept
floats, doubles, long doubles and even integer types as arguments.
To implement this polymorphism, the GCC __builtin_isgreater is defined
in builtins.def as a varargs function, and the compiler is expected to
issue the appropriate diagnostics if it isn't used in one of the
permissible ways (too many or too few arguments, neither argument of
a floating point type).


The following patch moves the remaining necessary functionality from
c-common.c to builtins.c.  This behaviour is already tested in the
dejagnu testsuite by gcc.dg/unordered-1.c.

The following patch has been tested (both on its own and in conjunction
with a patch to delete expand_unordered_cmp) on i686-pc-linux-gnu with
a complete "make bootstrap", all default languages, and regression
tested with a top-level "make -k check" with no new failures.

Committed to mainline CVS.



2004-06-19  Roger Sayle  <roger@eyesopen.com>

	* builtins.c (fold_builtin_unordered_cmp): Take an EXP argument
	instead of both an ARGLIST and a result TYPE.  Handle these C99
	comparison functions as "polymorphic" builtins.  Also handle
	lowering of BUILT_IN_ISUNORDERED to an UNORDERED_EXPR tree node.
	(fold_builtin_1): Update calls to fold_builtin_unordered_cmp.
	Move handling of BUILT_IN_ISUNORDERED from here to there.


Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.337
diff -c -3 -p -r1.337 builtins.c
*** builtins.c	12 Jun 2004 19:41:51 -0000	1.337
--- builtins.c	13 Jun 2004 20:55:14 -0000
*************** static tree fold_builtin_toascii (tree);
*** 168,175 ****
  static tree fold_builtin_isdigit (tree);
  static tree fold_builtin_fabs (tree, tree);
  static tree fold_builtin_abs (tree, tree);
! static tree fold_builtin_unordered_cmp (tree, tree, enum tree_code,
! 					enum tree_code);

  static tree simplify_builtin_memcmp (tree);
  static tree simplify_builtin_strcmp (tree);
--- 168,174 ----
  static tree fold_builtin_isdigit (tree);
  static tree fold_builtin_fabs (tree, tree);
  static tree fold_builtin_abs (tree, tree);
! static tree fold_builtin_unordered_cmp (tree, enum tree_code, enum tree_code);

  static tree simplify_builtin_memcmp (tree);
  static tree simplify_builtin_strcmp (tree);
*************** fold_builtin_abs (tree arglist, tree typ
*** 7618,7635 ****
     hold NaNs and ORDERED_CODE is used for the rest.  */

  static tree
! fold_builtin_unordered_cmp (tree arglist, tree type,
  			    enum tree_code unordered_code,
  			    enum tree_code ordered_code)
  {
    enum tree_code code;
    tree arg0, arg1;

    if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
!     return 0;

!   arg0 = TREE_VALUE (arglist);
!   arg1 = TREE_VALUE (TREE_CHAIN (arglist));

    code = MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
  						      : ordered_code;
--- 7617,7691 ----
     hold NaNs and ORDERED_CODE is used for the rest.  */

  static tree
! fold_builtin_unordered_cmp (tree exp,
  			    enum tree_code unordered_code,
  			    enum tree_code ordered_code)
  {
+   tree fndecl = get_callee_fndecl (exp);
+   tree arglist = TREE_OPERAND (exp, 1);
+   tree type = TREE_TYPE (TREE_TYPE (fndecl));
    enum tree_code code;
    tree arg0, arg1;

    if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
!     {
!       enum tree_code code0, code1;
!       tree type0, type1;
!       tree cmp_type = 0;

!       /* Check that we have exactly two arguments.  */
!       if (arglist == 0 || TREE_CHAIN (arglist) == 0)
! 	{
! 	  error ("too few arguments to function `%s'",
! 		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
! 	  return error_mark_node;
! 	}
!       else if (TREE_CHAIN (TREE_CHAIN (arglist)) != 0)
! 	{
! 	  error ("too many arguments to function `%s'",
! 		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
! 	  return error_mark_node;
! 	}
!
!       arg0 = TREE_VALUE (arglist);
!       arg1 = TREE_VALUE (TREE_CHAIN (arglist));
!
!       type0 = TREE_TYPE (arg0);
!       type1 = TREE_TYPE (arg1);
!
!       code0 = TREE_CODE (type0);
!       code1 = TREE_CODE (type1);
!
!       if (code0 == REAL_TYPE && code1 == REAL_TYPE)
! 	/* Choose the wider of two real types.  */
!         cmp_type = TYPE_PRECISION (type0) >= TYPE_PRECISION (type1)
! 		   ? type0 : type1;
!       else if (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
! 	cmp_type = type0;
!       else if (code0 == INTEGER_TYPE && code1 == REAL_TYPE)
! 	cmp_type = type1;
!       else
! 	{
! 	  error ("non-floating-point argument to function `%s'",
! 		 IDENTIFIER_POINTER (DECL_NAME (fndecl)));
! 	  return error_mark_node;
! 	}
!
!       arg0 = fold_convert (cmp_type, arg0);
!       arg1 = fold_convert (cmp_type, arg1);
!     }
!   else
!     {
!       arg0 = TREE_VALUE (arglist);
!       arg1 = TREE_VALUE (TREE_CHAIN (arglist));
!     }
!
!   if (unordered_code == UNORDERED_EXPR)
!     {
!       if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg0))))
! 	return omit_two_operands (type, integer_zero_node, arg0, arg1);
!       return fold (build2 (UNORDERED_EXPR, type, arg0, arg1));
!     }

    code = MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg0))) ? unordered_code
  						      : ordered_code;
*************** fold_builtin_1 (tree exp)
*** 8190,8215 ****
        return fold_builtin_copysign (arglist, type);

      case BUILT_IN_ISGREATER:
!       return fold_builtin_unordered_cmp (arglist, type, UNLE_EXPR, LE_EXPR);
      case BUILT_IN_ISGREATEREQUAL:
!       return fold_builtin_unordered_cmp (arglist, type, UNLT_EXPR, LT_EXPR);
      case BUILT_IN_ISLESS:
!       return fold_builtin_unordered_cmp (arglist, type, UNGE_EXPR, GE_EXPR);
      case BUILT_IN_ISLESSEQUAL:
!       return fold_builtin_unordered_cmp (arglist, type, UNGT_EXPR, GT_EXPR);
      case BUILT_IN_ISLESSGREATER:
!       return fold_builtin_unordered_cmp (arglist, type, UNEQ_EXPR, EQ_EXPR);
!
      case BUILT_IN_ISUNORDERED:
!       if (validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
! 	{
! 	  tree arg0 = TREE_VALUE (arglist);
! 	  tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
! 	  if (!MODE_HAS_NANS (TYPE_MODE (TREE_TYPE (arg0))))
! 	    return omit_two_operands (type, integer_zero_node, arg0, arg1);
! 	  return fold (build2 (UNORDERED_EXPR, type, arg0, arg1));
! 	}
!       break;

      default:
        break;
--- 8246,8262 ----
        return fold_builtin_copysign (arglist, type);

      case BUILT_IN_ISGREATER:
!       return fold_builtin_unordered_cmp (exp, UNLE_EXPR, LE_EXPR);
      case BUILT_IN_ISGREATEREQUAL:
!       return fold_builtin_unordered_cmp (exp, UNLT_EXPR, LT_EXPR);
      case BUILT_IN_ISLESS:
!       return fold_builtin_unordered_cmp (exp, UNGE_EXPR, GE_EXPR);
      case BUILT_IN_ISLESSEQUAL:
!       return fold_builtin_unordered_cmp (exp, UNGT_EXPR, GT_EXPR);
      case BUILT_IN_ISLESSGREATER:
!       return fold_builtin_unordered_cmp (exp, UNEQ_EXPR, EQ_EXPR);
      case BUILT_IN_ISUNORDERED:
!       return fold_builtin_unordered_cmp (exp, UNORDERED_EXPR, NOP_EXPR);

      default:
        break;

Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


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