Hello world,
this patch uses memcpy() directly when comparing two kind=1 strings of
equal and constant lengths. The test case modification depends
on the previous patch at
http://gcc.gnu.org/ml/gcc-patches/2013-03/msg00996.html
for setting the string lengths for substrings.
Regression-tested. No extra test case because the original test
cases have to be modified to avoid failure, and test the new
feature. OK for trunk after committing the patch above?
2013-03-25 Thomas Koenig <[email protected]>
* trans-expr.c (build_memcmp_call): New function.
(gfc_build_compare_string): If the kind=1 strings to be
compared have constant and equal lengths, use
memcmp().
2013-03-25 Thomas Koenig <[email protected]>
* gfortran.dg/character_comparison_3.f90: Adjust for use of memcmp
for constant and equal string lengths.
* gfortran.dg/character_comparison_5.f90: Likewise.
Index: fortran/trans-expr.c
===================================================================
--- fortran/trans-expr.c (Revision 196748)
+++ fortran/trans-expr.c (Arbeitskopie)
@@ -2655,6 +2665,32 @@ gfc_optimize_len_trim (tree len, tree str, int kin
return -1;
}
+/* Helper to build a call to memcmp. */
+
+static tree
+build_memcmp_call (tree s1, tree s2, tree n)
+{
+ tree tmp;
+
+ if (!POINTER_TYPE_P (TREE_TYPE (s1)))
+ s1 = gfc_build_addr_expr (pvoid_type_node, s1);
+ else
+ s1 = fold_convert (pvoid_type_node, s1);
+
+ if (!POINTER_TYPE_P (TREE_TYPE (s2)))
+ s2 = gfc_build_addr_expr (pvoid_type_node, s2);
+ else
+ s2 = fold_convert (pvoid_type_node, s2);
+
+ n = fold_convert (size_type_node, n);
+
+ tmp = build_call_expr_loc (input_location,
+ builtin_decl_explicit (BUILT_IN_MEMCMP),
+ 3, s1, s2, n);
+
+ return fold_convert (integer_type_node, tmp);
+}
+
/* Compare two strings. If they are all single characters, the result is the
subtraction of them. Otherwise, we build a library call. */
@@ -2698,7 +2734,13 @@ gfc_build_compare_string (tree len1, tree str1, tr
/* Build a call for the comparison. */
if (kind == 1)
- fndecl = gfor_fndecl_compare_string;
+ {
+ if (INTEGER_CST_P (len1) && INTEGER_CST_P (len2)
+ && tree_int_cst_equal (len1, len2))
+ return build_memcmp_call (str1, str2, len1);
+ else
+ fndecl = gfor_fndecl_compare_string;
+ }
else if (kind == 4)
fndecl = gfor_fndecl_compare_string_char4;
else
Index: testsuite/gfortran.dg/character_comparison_3.f90
===================================================================
--- testsuite/gfortran.dg/character_comparison_3.f90 (Revision 196748)
+++ testsuite/gfortran.dg/character_comparison_3.f90 (Arbeitskopie)
@@ -25,6 +25,7 @@ program main
if (c(:k3) == c(:k44)) call abort
end program main
-! { dg-final { scan-tree-dump-times "gfortran_compare_string" 8 "original" } }
+! { dg-final { scan-tree-dump-times "gfortran_compare_string" 6 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_memcmp" 2 "original" } }
! { dg-final { cleanup-tree-dump "original" } }
Index: testsuite/gfortran.dg/character_comparison_5.f90
===================================================================
--- testsuite/gfortran.dg/character_comparison_5.f90 (Revision 196748)
+++ testsuite/gfortran.dg/character_comparison_5.f90 (Arbeitskopie)
@@ -16,6 +16,6 @@ program main
end program main
! { dg-final { scan-tree-dump-times "gfortran_concat_string" 0 "original" } }
-! { dg-final { scan-tree-dump-times "gfortran_compare_string" 2 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_memcmp" 2 "original" } }
! { dg-final { cleanup-tree-dump "original" } }