diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-11-19 01:42:34 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-11-19 01:42:34 +0000 |
commit | 9db0f34dee98f95bac98026a3c8e004589ccdaa7 (patch) | |
tree | f2fcdd731a9c1bb632d77915060a8e36c94837b8 /gcc/builtins.c | |
parent | 2a372eebe07f3a6090d9e5cd28ef2477968b0151 (diff) | |
download | linaro-gcc-9db0f34dee98f95bac98026a3c8e004589ccdaa7.tar.gz linaro-gcc-9db0f34dee98f95bac98026a3c8e004589ccdaa7.tar.bz2 linaro-gcc-9db0f34dee98f95bac98026a3c8e004589ccdaa7.zip |
* md.texi (setmem): Document new parameter.
* optabs.c (maybe_gen_insn): Support 9 operands.
* builtins.c (determine_block_size): Add probable_max_size;
support anti-ranges.
(expand_builtin_memcpy. expand_builtin_memset_args): Pass around
probable_max_size.
* expr.c (emit_block_move_via_movmem, emit_block_move_hints,
emit_block_move, clear_storage_hints, set_storage_via_setmem):
Likewise.
* expr.h (emit_block_move_hints, clear_storage_hints,
set_storage_via_setmem): Update prototype.
* i386.md (setmem, movmem patterns): Add 9th operand.
* i386-protos.h (ix86_expand_set_or_movmem): Update prototype.
* i386.c (ix86_expand_set_or_movmem): Take probable_max_size_exp
argument; pass it to decide_alg.
* gcc.target/i386/memcpy-3.c: New testcase.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@204997 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 81 |
1 files changed, 55 insertions, 26 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index 39d40cb75e7..7dc980f9bf5 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -3096,12 +3096,15 @@ builtin_memcpy_read_str (void *data, HOST_WIDE_INT offset, } /* LEN specify length of the block of memcpy/memset operation. - Figure out its range and put it into MIN_SIZE/MAX_SIZE. */ + Figure out its range and put it into MIN_SIZE/MAX_SIZE. + In some cases we can make very likely guess on max size, then we + set it into PROBABLE_MAX_SIZE. */ static void determine_block_size (tree len, rtx len_rtx, unsigned HOST_WIDE_INT *min_size, - unsigned HOST_WIDE_INT *max_size) + unsigned HOST_WIDE_INT *max_size, + unsigned HOST_WIDE_INT *probable_max_size) { if (CONST_INT_P (len_rtx)) { @@ -3111,28 +3114,47 @@ determine_block_size (tree len, rtx len_rtx, else { double_int min, max; - if (TREE_CODE (len) == SSA_NAME - && get_range_info (len, &min, &max) == VR_RANGE) + enum value_range_type range_type = VR_UNDEFINED; + + /* Determine bounds from the type. */ + if (tree_fits_uhwi_p (TYPE_MIN_VALUE (TREE_TYPE (len)))) + *min_size = tree_to_uhwi (TYPE_MIN_VALUE (TREE_TYPE (len))); + else + *min_size = 0; + if (tree_fits_uhwi_p (TYPE_MAX_VALUE (TREE_TYPE (len)))) + *probable_max_size = *max_size = tree_to_uhwi (TYPE_MAX_VALUE (TREE_TYPE (len))); + else + *probable_max_size = *max_size = GET_MODE_MASK (GET_MODE (len_rtx)); + + if (TREE_CODE (len) == SSA_NAME) + range_type = get_range_info (len, &min, &max); + if (range_type == VR_RANGE) { - if (min.fits_uhwi ()) + if (min.fits_uhwi () && *min_size < min.to_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; + if (max.fits_uhwi () && *max_size > max.to_uhwi ()) + *probable_max_size = *max_size = max.to_uhwi (); } - else + else if (range_type == VR_ANTI_RANGE) { - if (tree_fits_uhwi_p (TYPE_MIN_VALUE (TREE_TYPE (len)))) - *min_size = tree_to_uhwi (TYPE_MIN_VALUE (TREE_TYPE (len))); - else - *min_size = 0; - if (tree_fits_uhwi_p (TYPE_MAX_VALUE (TREE_TYPE (len)))) - *max_size = tree_to_uhwi (TYPE_MAX_VALUE (TREE_TYPE (len))); - else - *max_size = GET_MODE_MASK (GET_MODE (len_rtx)); + /* Anti range 0...N lets us to determine minmal size to N+1. */ + if (min.is_zero ()) + { + if ((max + double_int_one).fits_uhwi ()) + *min_size = (max + double_int_one).to_uhwi (); + } + /* Code like + + int n; + if (n < 100) + memcpy (a,b, n) + + Produce anti range allowing negative values of N. We still + can use the information and make a guess that N is not negative. + */ + else if (!max.ule (double_int_one.lshift (30)) + && min.fits_uhwi ()) + *probable_max_size = min.to_uhwi () - 1; } } gcc_checking_assert (*max_size <= @@ -3164,6 +3186,7 @@ expand_builtin_memcpy (tree exp, rtx target) unsigned int expected_align = 0; unsigned HOST_WIDE_INT min_size; unsigned HOST_WIDE_INT max_size; + unsigned HOST_WIDE_INT probable_max_size; /* If DEST is not a pointer type, call the normal function. */ if (dest_align == 0) @@ -3183,7 +3206,8 @@ 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); + determine_block_size (len, len_rtx, &min_size, &max_size, + &probable_max_size); src_str = c_getstr (src); /* If SRC is a string constant and block move would be done @@ -3213,7 +3237,7 @@ expand_builtin_memcpy (tree exp, rtx target) CALL_EXPR_TAILCALL (exp) ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL, expected_align, expected_size, - min_size, max_size); + min_size, max_size, probable_max_size); if (dest_addr == 0) { @@ -3629,6 +3653,7 @@ expand_builtin_memset_args (tree dest, tree val, tree len, unsigned int expected_align = 0; unsigned HOST_WIDE_INT min_size; unsigned HOST_WIDE_INT max_size; + unsigned HOST_WIDE_INT probable_max_size; dest_align = get_pointer_alignment (dest); @@ -3657,7 +3682,8 @@ 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); + determine_block_size (len, len_rtx, &min_size, &max_size, + &probable_max_size); dest_mem = get_memory_rtx (dest, len); val_mode = TYPE_MODE (unsigned_char_type_node); @@ -3684,7 +3710,8 @@ 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, min_size, max_size)) + expected_size, min_size, max_size, + probable_max_size)) goto do_libcall; dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); @@ -3706,7 +3733,8 @@ 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, min_size, max_size)) + expected_size, min_size, max_size, + probable_max_size)) goto do_libcall; dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); @@ -3719,7 +3747,8 @@ expand_builtin_memset_args (tree dest, tree val, tree len, CALL_EXPR_TAILCALL (orig_exp) ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL, expected_align, expected_size, - min_size, max_size); + min_size, max_size, + probable_max_size); if (dest_addr == 0) { |