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]

Re: Patch for builtin fputs (first stdio opt ready for install)


 > From: Jason Merrill <jason@redhat.com>
 > 
 > You could save a pointer to the _DECL for __builtin_fputc in
 > c_common_nodes_and_builtins.
 > Jason


Here's what I came up with.  Bootstrapped on solaris2.7, no testsuite
regressions.  Okay to install?



2000-09-06  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>

	* builtins.c (built_in_decls): New array.
	(expand_builtin_fputs): New function.
	(expand_builtin): Handle BUILT_IN_FPUTC and BUILT_IN_FPUTS.

	* builtins.def (BUILT_IN_FPUTC, BUILT_IN_FPUTS): New members.

	* c-common.c (c_common_nodes_and_builtins): Handle fputc/fputs.

	* tree.h (built_in_decls): New array.

diff -rup orig/egcs-CVS20000905/gcc/builtins.c egcs-CVS20000905/gcc/builtins.c
--- orig/egcs-CVS20000905/gcc/builtins.c	Thu Aug 24 20:16:51 2000
+++ egcs-CVS20000905/gcc/builtins.c	Wed Sep  6 15:14:58 2000
@@ -67,6 +67,15 @@ const char *const built_in_names[(int) E
 };
 #undef DEF_BUILTIN
 
+/* Setup an array of _DECL trees, make sure each element is
+   initialized to NULL_TREE.  */
+#define DEF_BUILTIN(x) NULL_TREE,
+tree built_in_decls[(int) END_BUILTINS] =
+{
+#include "builtins.def"
+};
+#undef DEF_BUILTIN
+
 tree (*lang_type_promotes_to) PARAMS ((tree));
 
 static int get_pointer_alignment	PARAMS ((tree, unsigned));
@@ -102,6 +111,7 @@ static rtx expand_builtin_strlen	PARAMS 
 static rtx expand_builtin_alloca	PARAMS ((tree, rtx));
 static rtx expand_builtin_ffs		PARAMS ((tree, rtx, rtx));
 static rtx expand_builtin_frame_address	PARAMS ((tree));
+static rtx expand_builtin_fputs		PARAMS ((tree, int));
 static tree stabilize_va_list		PARAMS ((tree, int));
 static rtx expand_builtin_expect	PARAMS ((tree, rtx));
 
@@ -2310,6 +2320,60 @@ expand_builtin_ffs (arglist, target, sub
   return target;
 }
 
+/* If the string passed to fputs is a constant and is one character
+   long, we attempt to transform this call into __builtin_fputc(). */
+static rtx
+expand_builtin_fputs (arglist, ignore)
+     tree arglist;
+     int ignore;
+{
+  tree call_expr, len, stripped_string, newarglist;
+  tree fn = built_in_decls[BUILT_IN_FPUTC];
+
+  /* If the return value is used, or the replacement _DECL isn't
+     initialized, don't do the transformation. */
+  if (!ignore || !fn)
+    return 0;
+
+  /* Verify the arguments in the original call. */
+  if (arglist == 0
+      || (TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
+      || TREE_CHAIN (arglist) == 0
+      || (TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist))))
+	  != POINTER_TYPE))
+    return 0;
+
+  /* Get the length of the string passed to fputs. */
+  len = c_strlen (TREE_VALUE (arglist));
+  
+  /* If the length != 1, punt. */
+  if (len == 0 || compare_tree_int (len, 1))
+    return 0;
+
+  stripped_string = TREE_VALUE (arglist);
+  STRIP_NOPS (stripped_string);
+  if (stripped_string && TREE_CODE (stripped_string) == ADDR_EXPR)
+    stripped_string = TREE_OPERAND (stripped_string, 0);
+
+  /* New argument list transforming fputs(string, stream) to
+     fputc(string[0], stream).  */
+  newarglist = build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
+  newarglist =
+    tree_cons (NULL_TREE, 
+	       build_int_2 (TREE_STRING_POINTER (stripped_string)[0], 0),
+	       newarglist);
+  
+#ifdef TEST_STDIO_OPTS
+  warning ("Converted fputs(one-char-string, FILE*) -> fputc(char, FILE*)");
+#endif
+
+  call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
+  call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
+		     call_expr, newarglist, NULL_TREE);
+  TREE_SIDE_EFFECTS (call_expr) = 1;
+  return expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
+}
+
 /* Expand a call to __builtin_expect.  We return our argument and
    emit a NOTE_INSN_EXPECTED_VALUE note.  */
 
@@ -2383,7 +2447,8 @@ expand_builtin (exp, target, subtarget, 
 	  || fcode == BUILT_IN_MEMCPY || fcode == BUILT_IN_MEMCMP
 	  || fcode == BUILT_IN_BCMP || fcode == BUILT_IN_BZERO
 	  || fcode == BUILT_IN_STRLEN || fcode == BUILT_IN_STRCPY
-	  || fcode == BUILT_IN_STRCMP || fcode == BUILT_IN_FFS))
+	  || fcode == BUILT_IN_STRCMP || fcode == BUILT_IN_FFS
+	  || fcode == BUILT_IN_FPUTC || fcode == BUILT_IN_FPUTS))
     return expand_call (exp, target, ignore);
 
   switch (fcode)
@@ -2596,6 +2661,15 @@ expand_builtin (exp, target, subtarget, 
       emit_barrier ();
       return const0_rtx;
 
+    case BUILT_IN_FPUTC:
+      break;
+      
+    case BUILT_IN_FPUTS:
+      target = expand_builtin_fputs (arglist, ignore);
+      if (target)
+	return target;
+      break;
+      
       /* Various hooks for the DWARF 2 __throw routine.  */
     case BUILT_IN_UNWIND_INIT:
       expand_builtin_unwind_init ();
diff -rup orig/egcs-CVS20000905/gcc/builtins.def egcs-CVS20000905/gcc/builtins.def
--- orig/egcs-CVS20000905/gcc/builtins.def	Mon Apr 17 16:09:04 2000
+++ egcs-CVS20000905/gcc/builtins.def	Wed Sep  6 15:00:09 2000
@@ -58,6 +58,10 @@ DEF_BUILTIN(BUILT_IN_SETJMP)
 DEF_BUILTIN(BUILT_IN_LONGJMP)
 DEF_BUILTIN(BUILT_IN_TRAP)
 
+  /* Stdio builtins.  */
+DEF_BUILTIN(BUILT_IN_FPUTC)
+DEF_BUILTIN(BUILT_IN_FPUTS)
+
   /* ISO C99 floating point unordered comparisons.  */
 DEF_BUILTIN(BUILT_IN_ISGREATER)
 DEF_BUILTIN(BUILT_IN_ISGREATEREQUAL)
diff -rup orig/egcs-CVS20000905/gcc/c-common.c egcs-CVS20000905/gcc/c-common.c
--- orig/egcs-CVS20000905/gcc/c-common.c	Sun Sep  3 19:09:18 2000
+++ egcs-CVS20000905/gcc/c-common.c	Wed Sep  6 13:59:47 2000
@@ -4218,6 +4218,17 @@ c_common_nodes_and_builtins (cplus_mode,
 		    BUILT_IN_COS, BUILT_IN_NORMAL, "cos");
   builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
 		    BUILT_IN_COS, BUILT_IN_NORMAL, "cosl");
+  /* We declare these without argument so that the initial declaration
+     for these identifiers is a builtin.  That allows us to redeclare
+     them later with argument without worrying about the explicit
+     declarations in stdio.h being taken as the initial declaration.
+     Also, save the _DECL for these so we can use them later.  */
+  built_in_decls[BUILT_IN_FPUTC] =
+    builtin_function ("__builtin_fputc", int_ftype_any,
+		      BUILT_IN_FPUTC, BUILT_IN_NORMAL, "fputc");
+  built_in_decls[BUILT_IN_FPUTS] =
+    builtin_function ("__builtin_fputs", int_ftype_any,
+		      BUILT_IN_FPUTS, BUILT_IN_NORMAL, "fputs");
 
   if (! no_builtins)
     {
@@ -4260,6 +4271,15 @@ c_common_nodes_and_builtins (cplus_mode,
       builtin_function ("cos", double_ftype_double, BUILT_IN_COS,
 			BUILT_IN_NORMAL, NULL_PTR);
       builtin_function ("cosl", ldouble_ftype_ldouble, BUILT_IN_COS,
+			BUILT_IN_NORMAL, NULL_PTR);
+      /* We declare these without argument so that the initial
+         declaration for these identifiers is a builtin.  That allows
+         us to redeclare them later with argument without worrying
+         about the explicit declarations in stdio.h being taken as the
+         initial declaration.  */
+      builtin_function ("fputc", int_ftype_any, BUILT_IN_FPUTC,
+			BUILT_IN_NORMAL, NULL_PTR);
+      builtin_function ("fputs", int_ftype_any, BUILT_IN_FPUTS,
 			BUILT_IN_NORMAL, NULL_PTR);
 
       /* Declare these functions volatile
diff -rup orig/egcs-CVS20000905/gcc/tree.h egcs-CVS20000905/gcc/tree.h
--- orig/egcs-CVS20000905/gcc/tree.h	Thu Aug 31 09:28:48 2000
+++ egcs-CVS20000905/gcc/tree.h	Wed Sep  6 14:00:40 2000
@@ -96,6 +96,9 @@ enum built_in_function
 
 /* Names for the above.  */
 extern const char *const built_in_names[(int) END_BUILTINS];
+
+/* An array of _DECL trees for the above.  */
+extern union tree_node *built_in_decls[(int) END_BUILTINS];
 
 /* The definition of tree nodes fills the next several pages.  */
 


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