trans-expr.c (string_to_single_character): Also optimize string literals containing...
authorJakub Jelinek <jakub@redhat.com>
Tue, 13 Jul 2010 22:56:29 +0000 (00:56 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 13 Jul 2010 22:56:29 +0000 (00:56 +0200)
* trans-expr.c (string_to_single_character): Also optimize
string literals containing a single char followed only by spaces.
(gfc_trans_string_copy): Remove redundant string_to_single_character
calls.

From-SVN: r162161

gcc/fortran/ChangeLog
gcc/fortran/trans-expr.c

index 2847d945b6356a2668bf2000f62db06c77571dad..e8eeffc67609810582d6fbb9ab6b7134b9b3e3ff 100644 (file)
@@ -1,5 +1,10 @@
 2010-07-14  Jakub Jelinek  <jakub@redhat.com>
 
+       * trans-expr.c (string_to_single_character): Also optimize
+       string literals containing a single char followed only by spaces.
+       (gfc_trans_string_copy): Remove redundant string_to_single_character
+       calls.
+
        * trans-decl.c (gfc_build_intrinsic_function_decls,
        gfc_build_builtin_function_decls): Mark functions as
        DECL_PURE_P or TREE_READONLY.
index ff250fdbfee463d69d6edba2ad96f02590f71ce2..9857f4459e50835225ad7b844ddc9152a6a4c470 100644 (file)
@@ -1393,12 +1393,40 @@ string_to_single_character (tree len, tree str, int kind)
 {
   gcc_assert (POINTER_TYPE_P (TREE_TYPE (str)));
 
-  if (INTEGER_CST_P (len) && TREE_INT_CST_LOW (len) == 1
-      && TREE_INT_CST_HIGH (len) == 0)
+  if (!INTEGER_CST_P (len) || TREE_INT_CST_HIGH (len) != 0)
+    return NULL_TREE;
+
+  if (TREE_INT_CST_LOW (len) == 1)
     {
       str = fold_convert (gfc_get_pchar_type (kind), str);
-      return build_fold_indirect_ref_loc (input_location,
-                                     str);
+      return build_fold_indirect_ref_loc (input_location, str);
+    }
+
+  if (kind == 1
+      && TREE_CODE (str) == ADDR_EXPR
+      && TREE_CODE (TREE_OPERAND (str, 0)) == ARRAY_REF
+      && TREE_CODE (TREE_OPERAND (TREE_OPERAND (str, 0), 0)) == STRING_CST
+      && array_ref_low_bound (TREE_OPERAND (str, 0))
+        == TREE_OPERAND (TREE_OPERAND (str, 0), 1)
+      && TREE_INT_CST_LOW (len) > 1
+      && TREE_INT_CST_LOW (len)
+        == (unsigned HOST_WIDE_INT)
+           TREE_STRING_LENGTH (TREE_OPERAND (TREE_OPERAND (str, 0), 0)))
+    {
+      tree ret = fold_convert (gfc_get_pchar_type (kind), str);
+      ret = build_fold_indirect_ref_loc (input_location, ret);
+      if (TREE_CODE (ret) == INTEGER_CST)
+       {
+         tree string_cst = TREE_OPERAND (TREE_OPERAND (str, 0), 0);
+         int i, len = TREE_STRING_LENGTH (string_cst);
+         const char *ptr = TREE_STRING_POINTER (string_cst);
+
+         for (i = 1; i < len; i++)
+           if (ptr[i] != ' ')
+             return NULL_TREE;
+
+         return ret;
+       }
     }
 
   return NULL_TREE;
@@ -3556,7 +3584,7 @@ gfc_trans_string_copy (stmtblock_t * block, tree dlength, tree dest,
   if (dlength != NULL_TREE)
     {
       dlen = fold_convert (size_type_node, gfc_evaluate_now (dlength, block));
-      dsc = string_to_single_character (slen, dest, dkind);
+      dsc = string_to_single_character (dlen, dest, dkind);
     }
   else
     {
@@ -3564,12 +3592,6 @@ gfc_trans_string_copy (stmtblock_t * block, tree dlength, tree dest,
       dsc =  dest;
     }
 
-  if (slength != NULL_TREE && POINTER_TYPE_P (TREE_TYPE (src)))
-    ssc = string_to_single_character (slen, src, skind);
-  if (dlength != NULL_TREE && POINTER_TYPE_P (TREE_TYPE (dest)))
-    dsc = string_to_single_character (dlen, dest, dkind);
-
-
   /* Assign directly if the types are compatible.  */
   if (dsc != NULL_TREE && ssc != NULL_TREE
       && TREE_TYPE (dsc) == TREE_TYPE (ssc))