aboutsummaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2013-11-18 00:32:12 +0100
committerJan Hubicka <hubicka@gcc.gnu.org>2013-11-17 23:32:12 +0000
commit3918b10802ce96c0c8cf477a0695856dc8d0919a (patch)
tree947c4bdd1ca87f99c679541fdf303cfef4a00776 /gcc/builtins.c
parent2048a057063239900ff4b614c854f5a53bab55de (diff)
downloadgcc-3918b10802ce96c0c8cf477a0695856dc8d0919a.zip
gcc-3918b10802ce96c0c8cf477a0695856dc8d0919a.tar.gz
gcc-3918b10802ce96c0c8cf477a0695856dc8d0919a.tar.bz2
md.texi (setmem, movstr): Update documentation.
* doc/md.texi (setmem, movstr): Update documentation. * builtins.c (determine_block_size): New function. (expand_builtin_memcpy): Use it and pass it to emit_block_move_hints. (expand_builtin_memset_args): Use it and pass it to set_storage_via_setmem. * expr.c (emit_block_move_via_movmem): Add min_size/max_size parameters; update call to expander. (emit_block_move_hints): Add min_size/max_size parameters. (clear_storage_hints): Likewise. (set_storage_via_setmem): Likewise. (clear_storage): Update. * expr.h (emit_block_move_hints, clear_storage_hints, set_storage_via_setmem): Update prototype. * i386.c (ix86_expand_set_or_movmem): Add bounds; export. (ix86_expand_movmem, ix86_expand_setmem): Remove. (ix86_expand_movmem, ix86_expand_setmem): Remove. * i386.md (movmem, setmem): Pass parameters. * gcc.target/i386/memcpy-2.c: New testcase. From-SVN: r204926
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r--gcc/builtins.c61
1 files changed, 57 insertions, 4 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 7a04664..5c8577a 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -3095,6 +3095,51 @@ builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset,
return c_readstr (str + offset, mode);
}
+/* LEN specify length of the block of memcpy/memset operation.
+ Figure out its range and put it into MIN_SIZE/MAX_SIZE. */
+
+static void
+determine_block_size (tree len, rtx len_rtx,
+ unsigned HOST_WIDE_INT *min_size,
+ unsigned HOST_WIDE_INT *max_size)
+{
+ if (CONST_INT_P (len_rtx))
+ {
+ *min_size = *max_size = UINTVAL (len_rtx);
+ return;
+ }
+ else
+ {
+ double_int min, max;
+ if (TREE_CODE (len) == SSA_NAME
+ && get_range_info (len, &min, &max) == VR_RANGE)
+ {
+ if (min.fits_uhwi ())
+ *min_size = min.to_uhwi ();
+ else
+ *min_size = 0;
+ if (max.fits_uhwi ())
+ *max_size = max.to_uhwi ();
+ else
+ *max_size = (HOST_WIDE_INT)-1;
+ }
+ else
+ {
+ if (host_integerp (TYPE_MIN_VALUE (TREE_TYPE (len)), 1))
+ *min_size = tree_low_cst (TYPE_MIN_VALUE (TREE_TYPE (len)), 1);
+ else
+ *min_size = 0;
+ if (host_integerp (TYPE_MAX_VALUE (TREE_TYPE (len)), 1))
+ *max_size = tree_low_cst (TYPE_MAX_VALUE (TREE_TYPE (len)), 1);
+ else
+ *max_size = GET_MODE_MASK (GET_MODE (len_rtx));
+ }
+ }
+ gcc_checking_assert (*max_size <=
+ (unsigned HOST_WIDE_INT)
+ GET_MODE_MASK (GET_MODE (len_rtx)));
+}
+
/* Expand a call EXP to the memcpy builtin.
Return NULL_RTX if we failed, the caller should emit a normal call,
otherwise try to get the result in TARGET, if convenient (and in
@@ -3117,6 +3162,8 @@ expand_builtin_memcpy (tree exp, rtx target)
rtx dest_mem, src_mem, dest_addr, len_rtx;
HOST_WIDE_INT expected_size = -1;
unsigned int expected_align = 0;
+ unsigned HOST_WIDE_INT min_size;
+ unsigned HOST_WIDE_INT max_size;
/* If DEST is not a pointer type, call the normal function. */
if (dest_align == 0)
@@ -3136,6 +3183,7 @@ expand_builtin_memcpy (tree exp, rtx target)
dest_mem = get_memory_rtx (dest, len);
set_mem_align (dest_mem, dest_align);
len_rtx = expand_normal (len);
+ determine_block_size (len, len_rtx, &min_size, &max_size);
src_str = c_getstr (src);
/* If SRC is a string constant and block move would be done
@@ -3164,7 +3212,8 @@ expand_builtin_memcpy (tree exp, rtx target)
dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx,
CALL_EXPR_TAILCALL (exp)
? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
- expected_align, expected_size);
+ expected_align, expected_size,
+ min_size, max_size);
if (dest_addr == 0)
{
@@ -3578,6 +3627,8 @@ expand_builtin_memset_args (tree dest, tree val, tree len,
rtx dest_mem, dest_addr, len_rtx;
HOST_WIDE_INT expected_size = -1;
unsigned int expected_align = 0;
+ unsigned HOST_WIDE_INT min_size;
+ unsigned HOST_WIDE_INT max_size;
dest_align = get_pointer_alignment (dest);
@@ -3606,6 +3657,7 @@ expand_builtin_memset_args (tree dest, tree val, tree len,
len = builtin_save_expr (len);
len_rtx = expand_normal (len);
+ determine_block_size (len, len_rtx, &min_size, &max_size);
dest_mem = get_memory_rtx (dest, len);
val_mode = TYPE_MODE (unsigned_char_type_node);
@@ -3632,7 +3684,7 @@ expand_builtin_memset_args (tree dest, tree val, tree len,
}
else if (!set_storage_via_setmem (dest_mem, len_rtx, val_rtx,
dest_align, expected_align,
- expected_size))
+ expected_size, min_size, max_size))
goto do_libcall;
dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
@@ -3654,7 +3706,7 @@ expand_builtin_memset_args (tree dest, tree val, tree len,
else if (!set_storage_via_setmem (dest_mem, len_rtx,
gen_int_mode (c, val_mode),
dest_align, expected_align,
- expected_size))
+ expected_size, min_size, max_size))
goto do_libcall;
dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX);
@@ -3666,7 +3718,8 @@ expand_builtin_memset_args (tree dest, tree val, tree len,
dest_addr = clear_storage_hints (dest_mem, len_rtx,
CALL_EXPR_TAILCALL (orig_exp)
? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL,
- expected_align, expected_size);
+ expected_align, expected_size,
+ min_size, max_size);
if (dest_addr == 0)
{