aboutsummaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r--gcc/builtins.c152
1 files changed, 54 insertions, 98 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 11fd5687a0e..76be4a7f619 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -107,12 +107,12 @@ static rtx expand_builtin_memcmp (tree, tree, rtx, enum machine_mode);
static rtx expand_builtin_strcmp (tree, rtx, enum machine_mode);
static rtx expand_builtin_strncmp (tree, rtx, enum machine_mode);
static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
-static rtx expand_builtin_strcat (tree, rtx, enum machine_mode);
+static rtx expand_builtin_strcat (tree, tree, rtx, enum machine_mode);
static rtx expand_builtin_strncat (tree, rtx, enum machine_mode);
static rtx expand_builtin_strspn (tree, rtx, enum machine_mode);
static rtx expand_builtin_strcspn (tree, rtx, enum machine_mode);
static rtx expand_builtin_memcpy (tree, rtx, enum machine_mode);
-static rtx expand_builtin_mempcpy (tree, rtx, enum machine_mode, int);
+static rtx expand_builtin_mempcpy (tree, tree, rtx, enum machine_mode, int);
static rtx expand_builtin_memmove (tree, tree, rtx, enum machine_mode);
static rtx expand_builtin_bcopy (tree, tree);
static rtx expand_builtin_strcpy (tree, rtx, enum machine_mode);
@@ -162,7 +162,7 @@ static tree fold_builtin_ceil (tree);
static tree fold_builtin_round (tree);
static tree fold_builtin_bitop (tree);
static tree fold_builtin_memcpy (tree);
-static tree fold_builtin_mempcpy (tree);
+static tree fold_builtin_mempcpy (tree, tree, int);
static tree fold_builtin_memmove (tree, tree);
static tree fold_builtin_strchr (tree);
static tree fold_builtin_memcmp (tree);
@@ -2621,7 +2621,7 @@ expand_builtin_memcpy (tree exp, rtx target, enum machine_mode mode)
stpcpy. */
static rtx
-expand_builtin_mempcpy (tree arglist, rtx target, enum machine_mode mode,
+expand_builtin_mempcpy (tree arglist, tree type, rtx target, enum machine_mode mode,
int endp)
{
if (!validate_arglist (arglist,
@@ -2648,48 +2648,20 @@ expand_builtin_mempcpy (tree arglist, rtx target, enum machine_mode mode,
unsigned int dest_align
= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
rtx dest_mem, src_mem, len_rtx;
+ tree result = fold_builtin_mempcpy (arglist, type, endp);
- /* If DEST is not a pointer type, call the normal function. */
- if (dest_align == 0)
+ if (result)
+ return expand_expr (result, target, mode, EXPAND_NORMAL);
+
+ /* If either SRC or DEST is not a pointer type, don't do this
+ operation in-line. */
+ if (dest_align == 0 || src_align == 0)
return 0;
- /* If SRC and DEST are the same (and not volatile), do nothing. */
- if (operand_equal_p (src, dest, 0))
- {
- tree expr;
-
- if (endp == 0)
- {
- /* Evaluate and ignore LEN in case it has side-effects. */
- expand_expr (len, const0_rtx, VOIDmode, EXPAND_NORMAL);
- return expand_expr (dest, target, mode, EXPAND_NORMAL);
- }
-
- if (endp == 2)
- len = fold (build2 (MINUS_EXPR, TREE_TYPE (len), len,
- integer_one_node));
- len = fold_convert (TREE_TYPE (dest), len);
- expr = fold (build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len));
- return expand_expr (expr, target, mode, EXPAND_NORMAL);
- }
-
/* If LEN is not constant, call the normal function. */
if (! host_integerp (len, 1))
return 0;
- /* If the LEN parameter is zero, return DEST. */
- if (tree_low_cst (len, 1) == 0)
- {
- /* Evaluate and ignore SRC in case it has side-effects. */
- expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
- return expand_expr (dest, target, mode, EXPAND_NORMAL);
- }
-
- /* If either SRC is not a pointer type, don't do this
- operation in-line. */
- if (src_align == 0)
- return 0;
-
len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
src_str = c_getstr (src);
@@ -2779,7 +2751,7 @@ expand_builtin_memmove (tree arglist, tree type, rtx target,
it is ok to use memcpy as well. */
if (integer_onep (len))
{
- rtx ret = expand_builtin_mempcpy (arglist, target, mode,
+ rtx ret = expand_builtin_mempcpy (arglist, type, target, mode,
/*endp=*/0);
if (ret)
return ret;
@@ -2950,7 +2922,8 @@ expand_builtin_stpcpy (tree exp, rtx target, enum machine_mode mode)
narglist = build_tree_list (NULL_TREE, lenp1);
narglist = tree_cons (NULL_TREE, src, narglist);
narglist = tree_cons (NULL_TREE, dst, narglist);
- ret = expand_builtin_mempcpy (narglist, target, mode, /*endp=*/2);
+ ret = expand_builtin_mempcpy (narglist, TREE_TYPE (exp),
+ target, mode, /*endp=*/2);
if (ret)
return ret;
@@ -3010,35 +2983,21 @@ builtin_strncpy_read_str (void *data, HOST_WIDE_INT offset,
if we failed the caller should emit a normal call. */
static rtx
-expand_builtin_strncpy (tree arglist, rtx target, enum machine_mode mode)
+expand_builtin_strncpy (tree exp, rtx target, enum machine_mode mode)
{
- if (!validate_arglist (arglist,
- POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
- return 0;
- else
+ tree arglist = TREE_OPERAND (exp, 1);
+ if (validate_arglist (arglist,
+ POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
{
tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)), 1);
tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- tree fn;
-
- /* We must be passed a constant len parameter. */
- if (TREE_CODE (len) != INTEGER_CST)
- return 0;
-
- /* If the len parameter is zero, return the dst parameter. */
- if (integer_zerop (len))
- {
- /* Evaluate and ignore the src argument in case it has
- side-effects. */
- expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), const0_rtx,
- VOIDmode, EXPAND_NORMAL);
- /* Return the dst parameter. */
- return expand_expr (TREE_VALUE (arglist), target, mode,
- EXPAND_NORMAL);
- }
+ tree result = fold_builtin_strncpy (exp, slen);
+
+ if (result)
+ return expand_expr (result, target, mode, EXPAND_NORMAL);
- /* Now, we must be passed a constant src ptr parameter. */
- if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
+ /* We must be passed a constant len and src parameter. */
+ if (!host_integerp (len, 1) || !slen || !host_integerp (slen, 1))
return 0;
slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
@@ -3068,14 +3027,8 @@ expand_builtin_strncpy (tree arglist, rtx target, enum machine_mode mode)
dest_mem = convert_memory_address (ptr_mode, dest_mem);
return dest_mem;
}
-
- /* OK transform into builtin memcpy. */
- fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
- if (!fn)
- return 0;
- return expand_expr (build_function_call_expr (fn, arglist),
- target, mode, EXPAND_NORMAL);
}
+ return 0;
}
/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
@@ -3610,7 +3563,7 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
otherwise try to get the result in TARGET, if convenient. */
static rtx
-expand_builtin_strcat (tree arglist, rtx target, enum machine_mode mode)
+expand_builtin_strcat (tree arglist, tree type, rtx target, enum machine_mode mode)
{
if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
@@ -3660,7 +3613,7 @@ expand_builtin_strcat (tree arglist, rtx target, enum machine_mode mode)
pass in a target of zero, it should never actually be
used. If this was successful return the original
dst, not the result of mempcpy. */
- if (expand_builtin_mempcpy (arglist, /*target=*/0, mode, /*endp=*/0))
+ if (expand_builtin_mempcpy (arglist, type, /*target=*/0, mode, /*endp=*/0))
return expand_expr (dst, target, mode, EXPAND_NORMAL);
else
return 0;
@@ -5391,7 +5344,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
break;
case BUILT_IN_STRNCPY:
- target = expand_builtin_strncpy (arglist, target, mode);
+ target = expand_builtin_strncpy (exp, target, mode);
if (target)
return target;
break;
@@ -5403,7 +5356,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
break;
case BUILT_IN_STRCAT:
- target = expand_builtin_strcat (arglist, target, mode);
+ target = expand_builtin_strcat (arglist, TREE_TYPE (exp), target, mode);
if (target)
return target;
break;
@@ -5459,7 +5412,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
break;
case BUILT_IN_MEMPCPY:
- target = expand_builtin_mempcpy (arglist, target, mode, /*endp=*/ 1);
+ target = expand_builtin_mempcpy (arglist, TREE_TYPE (exp), target, mode, /*endp=*/ 1);
if (target)
return target;
break;
@@ -6991,31 +6944,34 @@ fold_builtin_memcpy (tree exp)
NULL_TREE if no simplification can be made. */
static tree
-fold_builtin_mempcpy (tree exp)
+fold_builtin_mempcpy (tree arglist, tree type, int endp)
{
- tree arglist = TREE_OPERAND (exp, 1);
- tree dest, src, len;
-
- if (!validate_arglist (arglist,
- POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
- return 0;
+ if (validate_arglist (arglist,
+ POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
+ {
+ tree dest = TREE_VALUE (arglist);
+ tree src = TREE_VALUE (TREE_CHAIN (arglist));
+ tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- dest = TREE_VALUE (arglist);
- src = TREE_VALUE (TREE_CHAIN (arglist));
- len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ /* If the LEN parameter is zero, return DEST. */
+ if (integer_zerop (len))
+ return omit_one_operand (type, dest, src);
- /* If the LEN parameter is zero, return DEST. */
- if (integer_zerop (len))
- return omit_one_operand (TREE_TYPE (exp), dest, src);
+ /* If SRC and DEST are the same (and not volatile), return DEST+LEN. */
+ if (operand_equal_p (src, dest, 0))
+ {
+ if (endp == 0)
+ return omit_one_operand (type, dest, len);
- /* If SRC and DEST are the same (and not volatile), return DEST+LEN. */
- if (operand_equal_p (src, dest, 0))
- {
- tree temp = fold_convert (TREE_TYPE (dest), len);
- temp = fold (build2 (PLUS_EXPR, TREE_TYPE (dest), dest, temp));
- return fold_convert (TREE_TYPE (exp), temp);
+ if (endp == 2)
+ len = fold (build2 (MINUS_EXPR, TREE_TYPE (len), len,
+ ssize_int (1)));
+
+ len = fold_convert (TREE_TYPE (dest), len);
+ len = fold (build2 (PLUS_EXPR, TREE_TYPE (dest), dest, len));
+ return fold_convert (type, len);
+ }
}
-
return 0;
}
@@ -7984,7 +7940,7 @@ fold_builtin_1 (tree exp, bool ignore)
return fold_builtin_memcpy (exp);
case BUILT_IN_MEMPCPY:
- return fold_builtin_mempcpy (exp);
+ return fold_builtin_mempcpy (arglist, type, /*endp=*/1);
case BUILT_IN_MEMMOVE:
return fold_builtin_memmove (arglist, type);