This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Patch for builtin fputs (first stdio opt ready for install)
- To: jason at redhat dot com
- Subject: Re: Patch for builtin fputs (first stdio opt ready for install)
- From: "Kaveh R. Ghazi" <ghazi at caip dot rutgers dot edu>
- Date: Thu, 7 Sep 2000 17:06:52 -0400 (EDT)
- Cc: gcc-patches at gcc dot gnu dot org
> 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. */