aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2019-02-16 12:20:33 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2019-02-16 12:20:33 +0100
commit3140b2ed036c51b9df0fda28b153ebecb4f906ec (patch)
tree81cea5780c130ecb2ea39b2cddc613799d6e31dc /gcc/expr.c
parent1f1d52e33df1b07c3d33b9fe377691ebbf4be157 (diff)
downloadgcc-3140b2ed036c51b9df0fda28b153ebecb4f906ec.zip
gcc-3140b2ed036c51b9df0fda28b153ebecb4f906ec.tar.gz
gcc-3140b2ed036c51b9df0fda28b153ebecb4f906ec.tar.bz2
re PR rtl-optimization/66152 (suboptimal load bytes to stack)
PR rtl-optimization/66152 * builtins.h (c_readstr): Declare. * builtins.c (c_readstr): Remove forward declaration. Add null_terminated_p argument, if false, read all bytes from the string instead of stopping after '\0'. * expr.c (string_cst_read_str): New function. (store_expr): Use string_cst_read_str instead of builtin_strncpy_read_str. Try to store by pieces the whole exp_len first, and only if that fails, split it up into store by pieces followed by clear_storage. Formatting fix. * gcc.target/i386/pr66152.c: New test. From-SVN: r268957
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c66
1 files changed, 43 insertions, 23 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 01ddf5a..ce71ae7 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -5453,6 +5453,30 @@ emit_storent_insn (rtx to, rtx from)
return maybe_expand_insn (code, 2, ops);
}
+/* Helper function for store_expr storing of STRING_CST. */
+
+static rtx
+string_cst_read_str (void *data, HOST_WIDE_INT offset, scalar_int_mode mode)
+{
+ tree str = (tree) data;
+
+ gcc_assert (offset >= 0);
+ if (offset >= TREE_STRING_LENGTH (str))
+ return const0_rtx;
+
+ if ((unsigned HOST_WIDE_INT) offset + GET_MODE_SIZE (mode)
+ > (unsigned HOST_WIDE_INT) TREE_STRING_LENGTH (str))
+ {
+ char *p = XALLOCAVEC (char, GET_MODE_SIZE (mode));
+ size_t l = TREE_STRING_LENGTH (str) - offset;
+ memcpy (p, TREE_STRING_POINTER (str) + offset, l);
+ memset (p + l, '\0', GET_MODE_SIZE (mode) - l);
+ return c_readstr (p, mode, false);
+ }
+
+ return c_readstr (TREE_STRING_POINTER (str) + offset, mode, false);
+}
+
/* Generate code for computing expression EXP,
and storing the value into TARGET.
@@ -5472,7 +5496,7 @@ emit_storent_insn (rtx to, rtx from)
rtx
store_expr (tree exp, rtx target, int call_param_p,
- bool nontemporal, bool reverse)
+ bool nontemporal, bool reverse)
{
rtx temp;
rtx alt_rtl = NULL_RTX;
@@ -5606,36 +5630,32 @@ store_expr (tree exp, rtx target, int call_param_p,
if (TREE_STRING_LENGTH (str) <= 0)
goto normal_expr;
- str_copy_len = strlen (TREE_STRING_POINTER (str));
- if (str_copy_len < TREE_STRING_LENGTH (str) - 1)
- goto normal_expr;
+ if (can_store_by_pieces (exp_len, string_cst_read_str, (void *) str,
+ MEM_ALIGN (target), false))
+ {
+ store_by_pieces (target, exp_len, string_cst_read_str, (void *) str,
+ MEM_ALIGN (target), false, RETURN_BEGIN);
+ return NULL_RTX;
+ }
str_copy_len = TREE_STRING_LENGTH (str);
- if ((STORE_MAX_PIECES & (STORE_MAX_PIECES - 1)) == 0
- && TREE_STRING_POINTER (str)[TREE_STRING_LENGTH (str) - 1] == '\0')
+ 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,
- CONST_CAST (char *, TREE_STRING_POINTER (str)),
- MEM_ALIGN (target), false))
+ if (str_copy_len >= exp_len)
+ goto normal_expr;
+
+ if (!can_store_by_pieces (str_copy_len, string_cst_read_str,
+ (void *) str, MEM_ALIGN (target), false))
goto normal_expr;
- dest_mem = target;
-
- memop_ret retmode = exp_len > str_copy_len ? RETURN_END : RETURN_BEGIN;
- dest_mem = store_by_pieces (dest_mem,
- str_copy_len, builtin_strncpy_read_str,
- CONST_CAST (char *,
- TREE_STRING_POINTER (str)),
- MEM_ALIGN (target), false,
- retmode);
- if (exp_len > str_copy_len)
- clear_storage (adjust_address (dest_mem, BLKmode, 0),
- GEN_INT (exp_len - str_copy_len),
- BLOCK_OP_NORMAL);
+ dest_mem = store_by_pieces (target, str_copy_len, string_cst_read_str,
+ (void *) str, MEM_ALIGN (target), false,
+ RETURN_END);
+ clear_storage (adjust_address (dest_mem, BLKmode, 0),
+ GEN_INT (exp_len - str_copy_len), BLOCK_OP_NORMAL);
return NULL_RTX;
}
else