aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2007-08-24 14:29:14 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2007-08-24 14:29:14 +0200
commit14a43348bc523d889df7918ae8672b233b2ccf37 (patch)
treee71678ea0f33cc3508fd3fe0dc995e4b09ea4872 /gcc/expr.c
parent492fc3e65ab2623ed56b8cbbcf0d8bd1c3552c12 (diff)
downloadgcc-14a43348bc523d889df7918ae8672b233b2ccf37.zip
gcc-14a43348bc523d889df7918ae8672b233b2ccf37.tar.gz
gcc-14a43348bc523d889df7918ae8672b233b2ccf37.tar.bz2
expr.c (store_expr): Optimize initialization of an array with STRING_CST.
* expr.c (store_expr): Optimize initialization of an array with STRING_CST. * expr.h (builtin_strncpy_read_str): New prototype. * builtins.c (builtin_strncpy_read_str): Remove prototype. No longer static. * gcc.dg/array-init-1.c: New test. From-SVN: r127769
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index a3b8132..97116b3 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -4472,10 +4472,52 @@ store_expr (tree exp, rtx target, int call_param_p, bool nontemporal)
return NULL_RTX;
}
+ else if (TREE_CODE (exp) == STRING_CST
+ && !nontemporal && !call_param_p
+ && TREE_STRING_LENGTH (exp) > 0
+ && TYPE_MODE (TREE_TYPE (exp)) == BLKmode)
+ {
+ /* Optimize initialization of an array with a STRING_CST. */
+ HOST_WIDE_INT exp_len, str_copy_len;
+ rtx dest_mem;
+
+ exp_len = int_expr_size (exp);
+ if (exp_len <= 0)
+ goto normal_expr;
+
+ str_copy_len = strlen (TREE_STRING_POINTER (exp));
+ if (str_copy_len < TREE_STRING_LENGTH (exp) - 1)
+ goto normal_expr;
+
+ str_copy_len = TREE_STRING_LENGTH (exp);
+ if ((STORE_MAX_PIECES & (STORE_MAX_PIECES - 1)) == 0)
+ {
+ str_copy_len += STORE_MAX_PIECES - 1;
+ str_copy_len &= ~(STORE_MAX_PIECES - 1);
+ }
+ str_copy_len = MIN (str_copy_len, exp_len);
+ if (!can_store_by_pieces (str_copy_len, builtin_strncpy_read_str,
+ (void *) TREE_STRING_POINTER (exp),
+ MEM_ALIGN (target)))
+ goto normal_expr;
+
+ dest_mem = target;
+
+ dest_mem = store_by_pieces (dest_mem,
+ str_copy_len, builtin_strncpy_read_str,
+ (void *) TREE_STRING_POINTER (exp),
+ MEM_ALIGN (target),
+ exp_len > str_copy_len ? 1 : 0);
+ if (exp_len > str_copy_len)
+ clear_storage (dest_mem, GEN_INT (exp_len - str_copy_len),
+ BLOCK_OP_NORMAL);
+ return NULL_RTX;
+ }
else
{
rtx tmp_target;
+ normal_expr:
/* If we want to use a nontemporal store, force the value to
register first. */
tmp_target = nontemporal ? NULL_RTX : target;