aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancois-Xavier Coudert <coudert@clipper.ens.fr>2006-07-12 17:11:11 +0200
committerFrançois-Xavier Coudert <fxcoudert@gcc.gnu.org>2006-07-12 15:11:11 +0000
commitb3eb1e0e9c1dc7cf7bf0a0d919a1a6239e37298b (patch)
tree72011c46efd76d2283de727ac46c303a3a63e36b
parent45e49d96406fc14662840eaf7d82b2bcbbbccab2 (diff)
downloadgcc-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/ChangeLog9
-rw-r--r--gcc/fortran/trans-decl.c8
-rw-r--r--gcc/fortran/trans-expr.c66
-rw-r--r--gcc/fortran/trans.h1
-rw-r--r--libgfortran/ChangeLog5
-rw-r--r--libgfortran/intrinsics/string_intrinsics.c23
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