summaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2013-11-19 01:42:34 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2013-11-19 01:42:34 +0000
commit9db0f34dee98f95bac98026a3c8e004589ccdaa7 (patch)
treef2fcdd731a9c1bb632d77915060a8e36c94837b8 /gcc/builtins.c
parent2a372eebe07f3a6090d9e5cd28ef2477968b0151 (diff)
downloadlinaro-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.c81
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)
{