diff options
author | Jan Hubicka <jh@suse.cz> | 2013-11-18 00:32:12 +0100 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2013-11-17 23:32:12 +0000 |
commit | 3918b10802ce96c0c8cf477a0695856dc8d0919a (patch) | |
tree | 947c4bdd1ca87f99c679541fdf303cfef4a00776 /gcc/builtins.c | |
parent | 2048a057063239900ff4b614c854f5a53bab55de (diff) | |
download | gcc-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.c | 61 |
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) { |