summaryrefslogtreecommitdiff
path: root/gcc/fortran/trans-expr.c
diff options
context:
space:
mode:
authortkoenig <tkoenig@138bc75d-0d04-0410-961f-82ee72b054a4>2013-03-30 10:19:02 +0000
committertkoenig <tkoenig@138bc75d-0d04-0410-961f-82ee72b054a4>2013-03-30 10:19:02 +0000
commit64390cdc66a6322798bd6cb35eeeba44e6388111 (patch)
tree2268fa99cea63797dc549729fa965505d884280a /gcc/fortran/trans-expr.c
parent211d6717148c6b313e0e1050cc1ed66c9e056259 (diff)
downloadgcc-64390cdc66a6322798bd6cb35eeeba44e6388111.tar.gz
2013-03-30 Thomas Koenig <tkoenig@gcc.gnu.org>
* trans-expr.c (build_memcmp_call): New function. (gfc_build_compare_string): If the strings compared have constant and equal lengths and the strings are kind=1, or, for kind=4 strings, the test is for (in)equality, use memcmp(). 2013-03-30 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. * gfortran.dg/character_comparison_9.f90: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@197261 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fortran/trans-expr.c')
-rw-r--r--gcc/fortran/trans-expr.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 98a54d9f688..454755bddb7 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -2689,6 +2689,32 @@ gfc_optimize_len_trim (tree len, tree str, int kind)
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. */
@@ -2730,6 +2756,26 @@ gfc_build_compare_string (tree len1, tree str1, tree len2, tree str2, int kind,
return integer_one_node;
}
+ /* We can compare via memcpy if the strings are known to be equal
+ in length and they are
+ - kind=1
+ - kind=4 and the comparision is for (in)equality. */
+
+ if (INTEGER_CST_P (len1) && INTEGER_CST_P (len2)
+ && tree_int_cst_equal (len1, len2)
+ && (kind == 1 || code == EQ_EXPR || code == NE_EXPR))
+ {
+ tree tmp;
+ tree chartype;
+
+ chartype = gfc_get_char_type (kind);
+ tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE(len1),
+ fold_convert (TREE_TYPE(len1),
+ TYPE_SIZE_UNIT(chartype)),
+ len1);
+ return build_memcmp_call (str1, str2, tmp);
+ }
+
/* Build a call for the comparison. */
if (kind == 1)
fndecl = gfor_fndecl_compare_string;