diff options
author | Francois-Xavier Coudert <coudert@clipper.ens.fr> | 2006-07-12 17:11:11 +0200 |
---|---|---|
committer | François-Xavier Coudert <fxcoudert@gcc.gnu.org> | 2006-07-12 15:11:11 +0000 |
commit | b3eb1e0e9c1dc7cf7bf0a0d919a1a6239e37298b (patch) | |
tree | 72011c46efd76d2283de727ac46c303a3a63e36b | |
parent | 45e49d96406fc14662840eaf7d82b2bcbbbccab2 (diff) | |
download | gcc-b3eb1e0e9c1dc7cf7bf0a0d919a1a6239e37298b.zip gcc-b3eb1e0e9c1dc7cf7bf0a0d919a1a6239e37298b.tar.gz gcc-b3eb1e0e9c1dc7cf7bf0a0d919a1a6239e37298b.tar.bz2 |
re PR fortran/28163 (Calling libgfortran's copy_string is inefficient)
PR fortran/28163
* trans-expr.c (gfc_trans_string_copy): Generate inline code
to perform string copying instead of calling a library function.
* trans-decl.c (gfc_build_intrinsic_function_decls): Don't build
decl for copy_string.
* trans.h (gfor_fndecl_copy_string): Remove prototype.
* intrinsics/string_intrinsics.c (copy_string): Remove function.
From-SVN: r115372
-rw-r--r-- | gcc/fortran/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/fortran/trans-decl.c | 8 | ||||
-rw-r--r-- | gcc/fortran/trans-expr.c | 66 | ||||
-rw-r--r-- | gcc/fortran/trans.h | 1 | ||||
-rw-r--r-- | libgfortran/ChangeLog | 5 | ||||
-rw-r--r-- | libgfortran/intrinsics/string_intrinsics.c | 23 |
6 files changed, 74 insertions, 38 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 74d1f71..89497e4 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,12 @@ +2006-07-12 Francois-Xavier Coudert <coudert@clipper.ens.fr> + + PR fortran/28163 + * trans-expr.c (gfc_trans_string_copy): Generate inline code + to perform string copying instead of calling a library function. + * trans-decl.c (gfc_build_intrinsic_function_decls): Don't build + decl for copy_string. + * trans.h (gfor_fndecl_copy_string): Remove prototype. + 2006-07-11 Feng Wang <fengwang@nudt.edu.cn> PR fortran/28213 diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index 14aee05..7398e16 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -121,7 +121,6 @@ tree gfor_fndecl_math_exponent16; /* String functions. */ -tree gfor_fndecl_copy_string; tree gfor_fndecl_compare_string; tree gfor_fndecl_concat_string; tree gfor_fndecl_string_len_trim; @@ -1938,13 +1937,6 @@ gfc_build_intrinsic_function_decls (void) tree gfc_c_int_type_node = gfc_get_int_type (gfc_c_int_kind); /* String functions. */ - gfor_fndecl_copy_string = - gfc_build_library_function_decl (get_identifier (PREFIX("copy_string")), - void_type_node, - 4, - gfc_charlen_type_node, pchar_type_node, - gfc_charlen_type_node, pchar_type_node); - gfor_fndecl_compare_string = gfc_build_library_function_decl (get_identifier (PREFIX("compare_string")), gfc_int4_type_node, diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 30cf80a..5c396ef 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -31,6 +31,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "toplev.h" #include "real.h" #include "tree-gimple.h" +#include "langhooks.h" #include "flags.h" #include "gfortran.h" #include "trans.h" @@ -2233,6 +2234,11 @@ gfc_trans_string_copy (stmtblock_t * block, tree dlen, tree dest, tree dsc; tree ssc; tree cond; + tree cond2; + tree tmp2; + tree tmp3; + tree tmp4; + stmtblock_t tempblock; /* Deal with single character specially. */ dsc = gfc_to_single_character (dlen, dest); @@ -2243,15 +2249,63 @@ gfc_trans_string_copy (stmtblock_t * block, tree dlen, tree dest, return; } + /* Do nothing if the destination length is zero. */ cond = fold_build2 (GT_EXPR, boolean_type_node, dlen, build_int_cst (gfc_charlen_type_node, 0)); - tmp = NULL_TREE; - tmp = gfc_chainon_list (tmp, dlen); - tmp = gfc_chainon_list (tmp, dest); - tmp = gfc_chainon_list (tmp, slen); - tmp = gfc_chainon_list (tmp, src); - tmp = build_function_call_expr (gfor_fndecl_copy_string, tmp); + /* The following code was previously in _gfortran_copy_string: + + // The two strings may overlap so we use memmove. + void + copy_string (GFC_INTEGER_4 destlen, char * dest, + GFC_INTEGER_4 srclen, const char * src) + { + if (srclen >= destlen) + { + // This will truncate if too long. + memmove (dest, src, destlen); + } + else + { + memmove (dest, src, srclen); + // Pad with spaces. + memset (&dest[srclen], ' ', destlen - srclen); + } + } + + We're now doing it here for better optimization, but the logic + is the same. */ + + /* Truncate string if source is too long. */ + cond2 = fold_build2 (GE_EXPR, boolean_type_node, slen, dlen); + tmp2 = gfc_chainon_list (NULL_TREE, dest); + tmp2 = gfc_chainon_list (tmp2, src); + tmp2 = gfc_chainon_list (tmp2, dlen); + tmp2 = build_function_call_expr (built_in_decls[BUILT_IN_MEMMOVE], tmp2); + + /* Else copy and pad with spaces. */ + tmp3 = gfc_chainon_list (NULL_TREE, dest); + tmp3 = gfc_chainon_list (tmp3, src); + tmp3 = gfc_chainon_list (tmp3, slen); + tmp3 = build_function_call_expr (built_in_decls[BUILT_IN_MEMMOVE], tmp3); + + tmp4 = fold_build2 (PLUS_EXPR, pchar_type_node, dest, + fold_convert (pchar_type_node, slen)); + tmp4 = gfc_chainon_list (NULL_TREE, tmp4); + tmp4 = gfc_chainon_list (tmp4, build_int_cst + (gfc_get_int_type (gfc_c_int_kind), + lang_hooks.to_target_charset (' '))); + tmp4 = gfc_chainon_list (tmp4, fold_build2 (MINUS_EXPR, TREE_TYPE(dlen), + dlen, slen)); + tmp4 = build_function_call_expr (built_in_decls[BUILT_IN_MEMSET], tmp4); + + gfc_init_block (&tempblock); + gfc_add_expr_to_block (&tempblock, tmp3); + gfc_add_expr_to_block (&tempblock, tmp4); + tmp3 = gfc_finish_block (&tempblock); + + /* The whole copy_string function is there. */ + tmp = fold_build3 (COND_EXPR, void_type_node, cond2, tmp2, tmp3); tmp = fold_build3 (COND_EXPR, void_type_node, cond, tmp, build_empty_stmt ()); gfc_add_expr_to_block (block, tmp); } diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h index ce99793..31d525d 100644 --- a/gcc/fortran/trans.h +++ b/gcc/fortran/trans.h @@ -508,7 +508,6 @@ extern GTY(()) tree gfor_fndecl_math_exponent10; extern GTY(()) tree gfor_fndecl_math_exponent16; /* String functions. */ -extern GTY(()) tree gfor_fndecl_copy_string; extern GTY(()) tree gfor_fndecl_compare_string; extern GTY(()) tree gfor_fndecl_concat_string; extern GTY(()) tree gfor_fndecl_string_len_trim; diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index a680112..b4478b4 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,8 @@ +2006-07-12 Francois-Xavier Coudert <coudert@clipper.ens.fr> + + PR fortran/28163 + * intrinsics/string_intrinsics.c (copy_string): Remove function. + 2006-07-04 Francois-Xavier Coudert <coudert@clipper.ens.fr> * intrinsics/date_and_time.c (itime0,idate0,itime_i4,itime_i8, diff --git a/libgfortran/intrinsics/string_intrinsics.c b/libgfortran/intrinsics/string_intrinsics.c index 1bc4ff2..fdaddef 100644 --- a/libgfortran/intrinsics/string_intrinsics.c +++ b/libgfortran/intrinsics/string_intrinsics.c @@ -44,9 +44,6 @@ Boston, MA 02110-1301, USA. */ /* String functions. */ -extern void copy_string (GFC_INTEGER_4, char *, GFC_INTEGER_4, const char *); -export_proto(copy_string); - extern void concat_string (GFC_INTEGER_4, char *, GFC_INTEGER_4, const char *, GFC_INTEGER_4, const char *); @@ -79,26 +76,6 @@ export_proto(string_trim); extern void string_repeat (char *, GFC_INTEGER_4, const char *, GFC_INTEGER_4); export_proto(string_repeat); -/* The two areas may overlap so we use memmove. */ - -void -copy_string (GFC_INTEGER_4 destlen, char * dest, - GFC_INTEGER_4 srclen, const char * src) -{ - if (srclen >= destlen) - { - /* This will truncate if too long. */ - memmove (dest, src, destlen); - } - else - { - memmove (dest, src, srclen); - /* Pad with spaces. */ - memset (&dest[srclen], ' ', destlen - srclen); - } -} - - /* Strings of unequal length are extended with pad characters. */ GFC_INTEGER_4 |