Patchwork [fortran] Use memcmp() for string comparison for constant-length kind=1 strings

login
register
mail settings
Submitter Thomas Koenig
Date March 25, 2013, 5 p.m.
Message ID <515082C3.9070602@netcologne.de>
Download mbox | patch
Permalink /patch/230756/
State New
Headers show

Comments

Thomas Koenig - March 25, 2013, 5 p.m.
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  <tkoenig@gcc.gnu.org>

         * 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  <tkoenig@gcc.gnu.org>

         * gfortran.dg/character_comparison_3.f90:  Adjust for use of memcmp
         for constant and equal string lengths.
         * gfortran.dg/character_comparison_5.f90:  Likewise.
Janne Blomqvist - March 26, 2013, 9:53 p.m.
On Mon, Mar 25, 2013 at 7:00 PM, Thomas Koenig <tkoenig@netcologne.de> wrote:
> 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  <tkoenig@gcc.gnu.org>
>
>         * 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  <tkoenig@gcc.gnu.org>
>
>         * gfortran.dg/character_comparison_3.f90:  Adjust for use of memcmp
>         for constant and equal string lengths.
>         * gfortran.dg/character_comparison_5.f90:  Likewise.

Ok. I think the same optimization could be done for kind=4 strings as
well, but nobody probably uses those anyway..
Ondrej Bilka - March 27, 2013, 8:16 a.m.
On Tue, Mar 26, 2013 at 11:53:27PM +0200, Janne Blomqvist wrote:
> On Mon, Mar 25, 2013 at 7:00 PM, Thomas Koenig <tkoenig@netcologne.de> wrote:
> > 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
> >
Could you omit of equal lengths part? Do memcmp with minimum of lengths
and if not equal call compare_string for suffixes.

> > 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  <tkoenig@gcc.gnu.org>
> >
> >         * 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  <tkoenig@gcc.gnu.org>
> >
> >         * gfortran.dg/character_comparison_3.f90:  Adjust for use of memcmp
> >         for constant and equal string lengths.
> >         * gfortran.dg/character_comparison_5.f90:  Likewise.
> 
> Ok. I think the same optimization could be done for kind=4 strings as
> well, but nobody probably uses those anyway..
> 
> 
> -- 
> Janne Blomqvist

Patch

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" } }