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] middle-end & C-frontend: fix PR middle-end/32668


This patch addresses PR middle-end/32668, which is a problem with
type-generic builtins.  Because they are implemented with variadic
prototypes, these builtins promote float to double which can either cause
pessimization and/or incorrect code generated from the middle-end.

My solution (suggested by Joseph) was to create a new internal-only
attribute to mark variadic builtins as "type generic" which notifies GCC
not to do the default C promotions for these calls.  This was discussed in
this thread: http://gcc.gnu.org/ml/gcc/2007-07/msg00221.html

I didn't document the builtin because the only other internal-only builtin
"no vops" wasn't document either AFAICT.  I could be convinced to document
"type generic" if necessary, but I don't want to confuse users who can't
use it anyway.

Although we normally test patches in isolation, this patch needs my other
recent work to really get exercised.  So I combined this patch with the
other stuff I have submitted to make use of these type-generic builtins.
It was bootstrapped along with these patches (with some minor conflicts
resolved in builtins.def):

isinf:
http://gcc.gnu.org/ml/gcc-patches/2007-06/msg01103.html

isfinite:
http://gcc.gnu.org/ml/gcc-patches/2007-06/msg01211.html

isnormal:
http://gcc.gnu.org/ml/gcc-patches/2007-06/msg01292.html

Check/test subnormals:
http://gcc.gnu.org/ml/gcc-patches/2007-07/msg00063.html

Add more testcases (& temporarily fix solaris fixincludes):
http://gcc.gnu.org/ml/gcc-patches/2007-07/msg00583.html

Remove solaris fixincludes hacks, rely only on builtins:
http://gcc.gnu.org/ml/gcc-patches/2007-06/msg01478.html


Bootstrap and regtest passed.  This can go in either before or after any
of the above patches.  It's only when they're all combined that you notice
the need for it in the isnormal builtin which gets more rigorously checked
through my extra testcases.

Okay for mainline?

		Thanks,
		--Kaveh



2007-07-07  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>

	PR middle-end/32668

	* builtin-attrs.def (ATTR_TYPEGENERIC,
	ATTR_CONST_NOTHROW_TYPEGENERIC): New.

	* builtins.def (BUILT_IN_ISINF, BUILT_IN_ISNAN,
	BUILT_IN_ISGREATER, BUILT_IN_ISGREATEREQUAL, BUILT_IN_ISLESS,
	BUILT_IN_ISLESSEQUAL, BUILT_IN_ISLESSGREATER,
	BUILT_IN_ISUNORDERED): Use ATTR_CONST_NOTHROW_TYPEGENERIC.

	* c-common.c (handle_type_generic_attribute): New.
	(c_common_attribute_table): Add "type generic".

	* c-typeck.c (convert_arguments): Handle "type generic" functions.

diff -rup orig/egcc-SVN20070706/gcc/builtin-attrs.def egcc-SVN20070706/gcc/builtin-attrs.def
--- orig/egcc-SVN20070706/gcc/builtin-attrs.def	2006-01-23 00:24:01.000000000 -0500
+++ egcc-SVN20070706/gcc/builtin-attrs.def	2007-07-07 17:25:40.785175001 -0400
@@ -94,6 +94,7 @@ DEF_ATTR_IDENT (ATTR_SCANF, "scanf")
 DEF_ATTR_IDENT (ATTR_SENTINEL, "sentinel")
 DEF_ATTR_IDENT (ATTR_STRFMON, "strfmon")
 DEF_ATTR_IDENT (ATTR_STRFTIME, "strftime")
+DEF_ATTR_IDENT (ATTR_TYPEGENERIC, "type generic")

 DEF_ATTR_TREE_LIST (ATTR_NOVOPS_LIST, ATTR_NOVOPS, ATTR_NULL, ATTR_NULL)

@@ -142,6 +143,9 @@ DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL
 /* Nothrow const functions whose pointer parameter(s) are all nonnull.  */
 DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_NONNULL, ATTR_CONST, ATTR_NULL, \
 			ATTR_NOTHROW_NONNULL)
+/* Nothrow const functions which are type-generic.  */
+DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_TYPEGENERIC, ATTR_TYPEGENERIC, ATTR_NULL, \
+			ATTR_CONST_NOTHROW_LIST)
 /* Nothrow pure functions whose pointer parameter(s) are all nonnull.  */
 DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_NONNULL, ATTR_PURE, ATTR_NULL, \
 			ATTR_NOTHROW_NONNULL)
diff -rup orig/egcc-SVN20070706/gcc/builtins.def egcc-SVN20070706/gcc/builtins.def
--- orig/egcc-SVN20070706/gcc/builtins.def	2007-05-17 23:03:49.000000000 -0400
+++ egcc-SVN20070706/gcc/builtins.def	2007-07-07 13:06:50.789804475 -0400
@@ -653,24 +653,24 @@ 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_C99_C90RES_BUILTIN (BUILT_IN_ISINF, "isinf", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
+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)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISINFD32, "isinfd32", BT_FN_INT_DFLOAT32, ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISINFD64, "isinfd64", BT_FN_INT_DFLOAT64, ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISINFD128, "isinfd128", BT_FN_INT_DFLOAT128, ATTR_CONST_NOTHROW_LIST)
-DEF_C99_C90RES_BUILTIN (BUILT_IN_ISNAN, "isnan", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_ISNAN, "isnan", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISNANF, "isnanf", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISNANL, "isnanl", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISNAND32, "isnand32", BT_FN_INT_DFLOAT32, ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISNAND64, "isnand64", BT_FN_INT_DFLOAT64, ATTR_CONST_NOTHROW_LIST)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_ISNAND128, "isnand128", BT_FN_INT_DFLOAT128, ATTR_CONST_NOTHROW_LIST)
-DEF_GCC_BUILTIN        (BUILT_IN_ISGREATER, "isgreater", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
-DEF_GCC_BUILTIN        (BUILT_IN_ISGREATEREQUAL, "isgreaterequal", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
-DEF_GCC_BUILTIN        (BUILT_IN_ISLESS, "isless", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
-DEF_GCC_BUILTIN        (BUILT_IN_ISLESSEQUAL, "islessequal", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
-DEF_GCC_BUILTIN        (BUILT_IN_ISLESSGREATER, "islessgreater", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
-DEF_GCC_BUILTIN        (BUILT_IN_ISUNORDERED, "isunordered", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
+DEF_GCC_BUILTIN        (BUILT_IN_ISGREATER, "isgreater", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC)
+DEF_GCC_BUILTIN        (BUILT_IN_ISGREATEREQUAL, "isgreaterequal", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC)
+DEF_GCC_BUILTIN        (BUILT_IN_ISLESS, "isless", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC)
+DEF_GCC_BUILTIN        (BUILT_IN_ISLESSEQUAL, "islessequal", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC)
+DEF_GCC_BUILTIN        (BUILT_IN_ISLESSGREATER, "islessgreater", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC)
+DEF_GCC_BUILTIN        (BUILT_IN_ISUNORDERED, "isunordered", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC)
 DEF_LIB_BUILTIN        (BUILT_IN_LABS, "labs", BT_FN_LONG_LONG, ATTR_CONST_NOTHROW_LIST)
 DEF_C99_BUILTIN        (BUILT_IN_LLABS, "llabs", BT_FN_LONGLONG_LONGLONG, ATTR_CONST_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_LONGJMP, "longjmp", BT_FN_VOID_PTR_INT, ATTR_NORETURN_NOTHROW_LIST)
diff -rup orig/egcc-SVN20070706/gcc/c-common.c egcc-SVN20070706/gcc/c-common.c
--- orig/egcc-SVN20070706/gcc/c-common.c	2007-07-06 23:02:59.000000000 -0400
+++ egcc-SVN20070706/gcc/c-common.c	2007-07-07 22:26:22.700596254 -0400
@@ -555,6 +555,7 @@ static tree handle_cleanup_attribute (tr
 static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
 						 bool *);
 static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
+static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
 static tree handle_alloc_size_attribute (tree *, tree, tree, int, bool *);

 static void check_function_nonnull (tree, int, tree *);
@@ -650,6 +651,10 @@ const struct attribute_spec c_common_att
 			      handle_warn_unused_result_attribute },
   { "sentinel",               0, 1, false, true, true,
 			      handle_sentinel_attribute },
+  /* For internal use (marking of builtins) only.  The name contains space
+     to prevent its usage in source code.  */
+  { "type generic",           0, 0, false, true, true,
+			      handle_type_generic_attribute },
   { "alloc_size",	      1, 2, false, true, true,
 			      handle_alloc_size_attribute },
   { "cold",                   0, 0, true,  false, false,
@@ -6154,6 +6159,19 @@ handle_sentinel_attribute (tree *node, t

   return NULL_TREE;
 }
+
+/* Handle a "type_generic" attribute.  */
+
+static tree
+handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
+			       tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+			       bool * ARG_UNUSED (no_add_attrs))
+{
+  /* Ensure we have a function type, with no arguments.  */
+  gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE && ! TYPE_ARG_TYPES (*node));
+
+  return NULL_TREE;
+}

 /* Check for valid arguments being passed to a function.
    ATTRS is a list of attributes.  There are NARGS arguments in the array
diff -rup orig/egcc-SVN20070706/gcc/c-typeck.c egcc-SVN20070706/gcc/c-typeck.c
--- orig/egcc-SVN20070706/gcc/c-typeck.c	2007-06-30 23:02:59.000000000 -0400
+++ egcc-SVN20070706/gcc/c-typeck.c	2007-07-07 22:38:07.561282964 -0400
@@ -2394,6 +2394,8 @@ convert_arguments (int nargs, tree *arga
 {
   tree typetail, valtail;
   int parmnum;
+  const bool type_generic = fundecl
+    && lookup_attribute ("type generic", TYPE_ATTRIBUTES(TREE_TYPE (fundecl)));
   tree selector;

   /* Change pointer to function to the function itself for
@@ -2585,8 +2587,13 @@ convert_arguments (int nargs, tree *arga
 	       && (TYPE_PRECISION (TREE_TYPE (val))
 		   < TYPE_PRECISION (double_type_node))
 	       && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (val))))
-	/* Convert `float' to `double'.  */
-	argarray[parmnum] = convert (double_type_node, val);
+        {
+	  /* Convert `float' to `double'.  */
+	  if (type_generic)
+	    argarray[parmnum] = val;
+	  else
+	    argarray[parmnum] = convert (double_type_node, val);
+	}
       else if ((invalid_func_diag =
 		targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val)))
 	{


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