Commit c2bd38e8 by Roger Sayle Committed by Richard Henderson

builtins.c (expand_builtin_memset, [...]): Additional arguments TARGET and MODE.

        * builtins.c (expand_builtin_memset, expand_builtin_memcpy,
        expand_builtin_strcpy): Additional arguments TARGET and MODE.
        (expand_builtin_bzero, expand_builtin_strcpy,
        expand_builtin_strncpy, expand_builtin_bzero): Pass additional
        TARGET and MODE parameters to the above functions.
        (expand_builtin_memset, expand_builtin_memcpy): Optimize the
        case where the LEN parameter is constant zero.
        (expand_builtin_memcmp): No longer conditional on
        HAVE_cmpstrsi.  Take an additional mode parameter.  Optimize
        the cases where len is either constant zero or one.
        Optimize to call to memcpy, even if the memcpy isn't inlined.
        (expand_builtin_strncpy): Optimize to call memcpy, even if the
        memcpy isn't inlined.
        (expand_builtin_strcmp, expand_builtin_strncmp): Always attempt
        to optimize to a call to memcmp.
        (expand_builtin): expand_builtin_memcmp can always be called,
        and pass the required parameters to expand_builtin_memcmp,
        expand_builtin_memset, expand_builtin_memcpy and
        expand_builtin_strcpy.

        * gcc.c-torture/execute/string-opt-14.c: New test case.
        * gcc.c-torture/execute/string-opt-15.c: New test case.

From-SVN: r47960
parent 897bb55f
2001-12-12 Roger Sayle <roger@eyesopen.com>
* builtins.c (expand_builtin_memset, expand_builtin_memcpy,
expand_builtin_strcpy): Additional arguments TARGET and MODE.
(expand_builtin_bzero, expand_builtin_strcpy,
expand_builtin_strncpy, expand_builtin_bzero): Pass additional
TARGET and MODE parameters to the above functions.
(expand_builtin_memset, expand_builtin_memcpy): Optimize the
case where the LEN parameter is constant zero.
(expand_builtin_memcmp): No longer conditional on
HAVE_cmpstrsi. Take an additional mode parameter. Optimize
the cases where len is either constant zero or one.
Optimize to call to memcpy, even if the memcpy isn't inlined.
(expand_builtin_strncpy): Optimize to call memcpy, even if the
memcpy isn't inlined.
(expand_builtin_strcmp, expand_builtin_strncmp): Always attempt
to optimize to a call to memcmp.
(expand_builtin): expand_builtin_memcmp can always be called,
and pass the required parameters to expand_builtin_memcmp,
expand_builtin_memset, expand_builtin_memcpy and
expand_builtin_strcpy.
2001-12-12 David O'Brien <obrien@FreeBSD.org> 2001-12-12 David O'Brien <obrien@FreeBSD.org>
* config.gcc (arm-*-freebsd*): Add target. * config.gcc (arm-*-freebsd*): Add target.
......
...@@ -101,9 +101,8 @@ static rtx expand_builtin_next_arg PARAMS ((tree)); ...@@ -101,9 +101,8 @@ static rtx expand_builtin_next_arg PARAMS ((tree));
static rtx expand_builtin_va_start PARAMS ((int, tree)); static rtx expand_builtin_va_start PARAMS ((int, tree));
static rtx expand_builtin_va_end PARAMS ((tree)); static rtx expand_builtin_va_end PARAMS ((tree));
static rtx expand_builtin_va_copy PARAMS ((tree)); static rtx expand_builtin_va_copy PARAMS ((tree));
#ifdef HAVE_cmpstrsi static rtx expand_builtin_memcmp PARAMS ((tree, tree, rtx,
static rtx expand_builtin_memcmp PARAMS ((tree, tree, rtx)); enum machine_mode));
#endif
static rtx expand_builtin_strcmp PARAMS ((tree, rtx, static rtx expand_builtin_strcmp PARAMS ((tree, rtx,
enum machine_mode)); enum machine_mode));
static rtx expand_builtin_strncmp PARAMS ((tree, rtx, static rtx expand_builtin_strncmp PARAMS ((tree, rtx,
...@@ -118,15 +117,18 @@ static rtx expand_builtin_strspn PARAMS ((tree, rtx, ...@@ -118,15 +117,18 @@ static rtx expand_builtin_strspn PARAMS ((tree, rtx,
enum machine_mode)); enum machine_mode));
static rtx expand_builtin_strcspn PARAMS ((tree, rtx, static rtx expand_builtin_strcspn PARAMS ((tree, rtx,
enum machine_mode)); enum machine_mode));
static rtx expand_builtin_memcpy PARAMS ((tree)); static rtx expand_builtin_memcpy PARAMS ((tree, rtx,
static rtx expand_builtin_strcpy PARAMS ((tree)); enum machine_mode));
static rtx expand_builtin_strcpy PARAMS ((tree, rtx,
enum machine_mode));
static rtx builtin_strncpy_read_str PARAMS ((PTR, HOST_WIDE_INT, static rtx builtin_strncpy_read_str PARAMS ((PTR, HOST_WIDE_INT,
enum machine_mode)); enum machine_mode));
static rtx expand_builtin_strncpy PARAMS ((tree, rtx, static rtx expand_builtin_strncpy PARAMS ((tree, rtx,
enum machine_mode)); enum machine_mode));
static rtx builtin_memset_read_str PARAMS ((PTR, HOST_WIDE_INT, static rtx builtin_memset_read_str PARAMS ((PTR, HOST_WIDE_INT,
enum machine_mode)); enum machine_mode));
static rtx expand_builtin_memset PARAMS ((tree)); static rtx expand_builtin_memset PARAMS ((tree, rtx,
enum machine_mode));
static rtx expand_builtin_bzero PARAMS ((tree)); static rtx expand_builtin_bzero PARAMS ((tree));
static rtx expand_builtin_strlen PARAMS ((tree, rtx)); static rtx expand_builtin_strlen PARAMS ((tree, rtx));
static rtx expand_builtin_strstr PARAMS ((tree, rtx, static rtx expand_builtin_strstr PARAMS ((tree, rtx,
...@@ -1910,11 +1912,16 @@ builtin_memcpy_read_str (data, offset, mode) ...@@ -1910,11 +1912,16 @@ builtin_memcpy_read_str (data, offset, mode)
return c_readstr (str + offset, mode); return c_readstr (str + offset, mode);
} }
/* Expand a call to the memcpy builtin, with arguments in ARGLIST. */ /* Expand a call to the memcpy builtin, with arguments in ARGLIST.
Return 0 if we failed, the caller should emit a normal call, otherwise
try to get the result in TARGET, if convenient (and in mode MODE if
that's convenient). */
static rtx static rtx
expand_builtin_memcpy (arglist) expand_builtin_memcpy (arglist, target, mode)
tree arglist; tree arglist;
rtx target;
enum machine_mode mode;
{ {
if (!validate_arglist (arglist, if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
...@@ -1931,9 +1938,21 @@ expand_builtin_memcpy (arglist) ...@@ -1931,9 +1938,21 @@ expand_builtin_memcpy (arglist)
= get_pointer_alignment (dest, BIGGEST_ALIGNMENT); = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
rtx dest_mem, src_mem, dest_addr, len_rtx; rtx dest_mem, src_mem, dest_addr, len_rtx;
/* If either SRC or DEST is not a pointer type, don't do /* If DEST is not a pointer type, call the normal function. */
this operation in-line. */ if (dest_align == 0)
if (src_align == 0 || dest_align == 0) return 0;
/* If the LEN parameter is zero, return DEST. */
if (host_integerp (len, 1) && 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; return 0;
dest_mem = get_memory_rtx (dest); dest_mem = get_memory_rtx (dest);
...@@ -1970,33 +1989,34 @@ expand_builtin_memcpy (arglist) ...@@ -1970,33 +1989,34 @@ expand_builtin_memcpy (arglist)
} }
/* Expand expression EXP, which is a call to the strcpy builtin. Return 0 /* Expand expression EXP, which is a call to the strcpy builtin. Return 0
if we failed the caller should emit a normal call. */ if we failed the caller should emit a normal call, otherwise try to get
the result in TARGET, if convenient (and in mode MODE if that's
convenient). */
static rtx static rtx
expand_builtin_strcpy (exp) expand_builtin_strcpy (exp, target, mode)
tree exp; tree exp;
rtx target;
enum machine_mode mode;
{ {
tree arglist = TREE_OPERAND (exp, 1); tree arglist = TREE_OPERAND (exp, 1);
rtx result; tree fn, len;
if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0; return 0;
else
{
tree len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
fn = built_in_decls[BUILT_IN_MEMCPY];
if (!fn)
return 0;
len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
if (len == 0) if (len == 0)
return 0; return 0;
len = size_binop (PLUS_EXPR, len, ssize_int (1)); len = size_binop (PLUS_EXPR, len, ssize_int (1));
chainon (arglist, build_tree_list (NULL_TREE, len)); chainon (arglist, build_tree_list (NULL_TREE, len));
} return expand_expr (build_function_call_expr (fn, arglist),
target, mode, EXPAND_NORMAL);
result = expand_builtin_memcpy (arglist);
if (! result)
TREE_CHAIN (TREE_CHAIN (arglist)) = 0;
return result;
} }
/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE) /* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
...@@ -2033,6 +2053,7 @@ expand_builtin_strncpy (arglist, target, mode) ...@@ -2033,6 +2053,7 @@ expand_builtin_strncpy (arglist, target, mode)
{ {
tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist))); tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
tree fn;
/* We must be passed a constant len parameter. */ /* We must be passed a constant len parameter. */
if (TREE_CODE (len) != INTEGER_CST) if (TREE_CODE (len) != INTEGER_CST)
...@@ -2081,7 +2102,11 @@ expand_builtin_strncpy (arglist, target, mode) ...@@ -2081,7 +2102,11 @@ expand_builtin_strncpy (arglist, target, mode)
} }
/* OK transform into builtin memcpy. */ /* OK transform into builtin memcpy. */
return expand_builtin_memcpy (arglist); fn = built_in_decls[BUILT_IN_MEMCPY];
if (!fn)
return 0;
return expand_expr (build_function_call_expr (fn, arglist),
target, mode, EXPAND_NORMAL);
} }
} }
...@@ -2104,11 +2129,15 @@ builtin_memset_read_str (data, offset, mode) ...@@ -2104,11 +2129,15 @@ builtin_memset_read_str (data, offset, mode)
} }
/* Expand expression EXP, which is a call to the memset builtin. Return 0 /* Expand expression EXP, which is a call to the memset builtin. Return 0
if we failed the caller should emit a normal call. */ if we failed the caller should emit a normal call, otherwise try to get
the result in TARGET, if convenient (and in mode MODE if that's
convenient). */
static rtx static rtx
expand_builtin_memset (exp) expand_builtin_memset (exp, target, mode)
tree exp; tree exp;
rtx target;
enum machine_mode mode;
{ {
tree arglist = TREE_OPERAND (exp, 1); tree arglist = TREE_OPERAND (exp, 1);
...@@ -2131,6 +2160,14 @@ expand_builtin_memset (exp) ...@@ -2131,6 +2160,14 @@ expand_builtin_memset (exp)
if (dest_align == 0) if (dest_align == 0)
return 0; return 0;
/* If the LEN parameter is zero, return DEST. */
if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
{
/* Evaluate and ignore VAL in case it has side-effects. */
expand_expr (val, const0_rtx, VOIDmode, EXPAND_NORMAL);
return expand_expr (dest, target, mode, EXPAND_NORMAL);
}
if (TREE_CODE (val) != INTEGER_CST) if (TREE_CODE (val) != INTEGER_CST)
return 0; return 0;
...@@ -2184,14 +2221,16 @@ expand_builtin_bzero (exp) ...@@ -2184,14 +2221,16 @@ expand_builtin_bzero (exp)
size = TREE_VALUE (TREE_CHAIN (arglist)); size = TREE_VALUE (TREE_CHAIN (arglist));
/* New argument list transforming bzero(ptr x, int y) to /* New argument list transforming bzero(ptr x, int y) to
memset(ptr x, int 0, size_t y). */ memset(ptr x, int 0, size_t y). This is done this way
so that if it isn't expanded inline, we fallback to
calling bzero instead of memset. */
newarglist = build_tree_list (NULL_TREE, convert (sizetype, size)); newarglist = build_tree_list (NULL_TREE, convert (sizetype, size));
newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist); newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
newarglist = tree_cons (NULL_TREE, dest, newarglist); newarglist = tree_cons (NULL_TREE, dest, newarglist);
TREE_OPERAND (exp, 1) = newarglist; TREE_OPERAND (exp, 1) = newarglist;
result = expand_builtin_memset(exp); result = expand_builtin_memset (exp, const0_rtx, VOIDmode);
/* Always restore the original arguments. */ /* Always restore the original arguments. */
TREE_OPERAND (exp, 1) = arglist; TREE_OPERAND (exp, 1) = arglist;
...@@ -2199,28 +2238,58 @@ expand_builtin_bzero (exp) ...@@ -2199,28 +2238,58 @@ expand_builtin_bzero (exp)
return result; return result;
} }
#ifdef HAVE_cmpstrsi
/* Expand expression EXP, which is a call to the memcmp or the strcmp builtin. /* Expand expression EXP, which is a call to the memcmp or the strcmp builtin.
ARGLIST is the argument list for this call. Return 0 if we failed and the ARGLIST is the argument list for this call. Return 0 if we failed and the
caller should emit a normal call, otherwise try to get the result in caller should emit a normal call, otherwise try to get the result in
TARGET, if convenient. */ TARGET, if convenient (and in mode MODE, if that's convenient). */
static rtx static rtx
expand_builtin_memcmp (exp, arglist, target) expand_builtin_memcmp (exp, arglist, target, mode)
tree exp; tree exp;
tree arglist; tree arglist;
rtx target; rtx target;
enum machine_mode mode;
{ {
tree arg1, arg2, len;
if (!validate_arglist (arglist, if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0; return 0;
arg1 = TREE_VALUE (arglist);
arg2 = TREE_VALUE (TREE_CHAIN (arglist));
len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
/* If the len parameter is zero, return zero. */
if (host_integerp (len, 1) && tree_low_cst (len, 1) == 0)
{
/* Evaluate and ignore arg1 and arg2 in case they have
side-effects. */
expand_expr (arg1, const0_rtx, VOIDmode, EXPAND_NORMAL);
expand_expr (arg2, const0_rtx, VOIDmode, EXPAND_NORMAL);
return const0_rtx;
}
/* If len parameter is one, return an expression corresponding to
(*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
if (host_integerp (len, 1) && tree_low_cst (len, 1) == 1)
{
tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
tree cst_uchar_ptr_node = build_pointer_type (cst_uchar_node);
tree ind1 =
fold (build1 (CONVERT_EXPR, integer_type_node,
build1 (INDIRECT_REF, cst_uchar_node,
build1 (NOP_EXPR, cst_uchar_ptr_node, arg1))));
tree ind2 =
fold (build1 (CONVERT_EXPR, integer_type_node,
build1 (INDIRECT_REF, cst_uchar_node,
build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
#ifdef HAVE_cmpstrsi
{ {
enum machine_mode mode;
tree arg1 = TREE_VALUE (arglist);
tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
rtx arg1_rtx, arg2_rtx, arg3_rtx; rtx arg1_rtx, arg2_rtx, arg3_rtx;
rtx result; rtx result;
rtx insn; rtx insn;
...@@ -2275,9 +2344,11 @@ expand_builtin_memcmp (exp, arglist, target) ...@@ -2275,9 +2344,11 @@ expand_builtin_memcmp (exp, arglist, target)
else else
return convert_to_mode (mode, result, 0); return convert_to_mode (mode, result, 0);
} }
}
#endif #endif
return 0;
}
/* Expand expression EXP, which is a call to the strcmp builtin. Return 0 /* Expand expression EXP, which is a call to the strcmp builtin. Return 0
if we failed the caller should emit a normal call, otherwise try to get if we failed the caller should emit a normal call, otherwise try to get
the result in TARGET, if convenient. */ the result in TARGET, if convenient. */
...@@ -2289,7 +2360,7 @@ expand_builtin_strcmp (exp, target, mode) ...@@ -2289,7 +2360,7 @@ expand_builtin_strcmp (exp, target, mode)
enum machine_mode mode; enum machine_mode mode;
{ {
tree arglist = TREE_OPERAND (exp, 1); tree arglist = TREE_OPERAND (exp, 1);
tree arg1, arg2; tree arg1, arg2, len, len2, fn;
const char *p1, *p2; const char *p1, *p2;
if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
...@@ -2325,14 +2396,8 @@ expand_builtin_strcmp (exp, target, mode) ...@@ -2325,14 +2396,8 @@ expand_builtin_strcmp (exp, target, mode)
return expand_expr (result, target, mode, EXPAND_NORMAL); return expand_expr (result, target, mode, EXPAND_NORMAL);
} }
#ifdef HAVE_cmpstrsi len = c_strlen (arg1);
if (! HAVE_cmpstrsi) len2 = c_strlen (arg2);
return 0;
{
tree len = c_strlen (arg1);
tree len2 = c_strlen (arg2);
rtx result;
if (len) if (len)
len = size_binop (PLUS_EXPR, ssize_int (1), len); len = size_binop (PLUS_EXPR, ssize_int (1), len);
...@@ -2367,16 +2432,13 @@ expand_builtin_strcmp (exp, target, mode) ...@@ -2367,16 +2432,13 @@ expand_builtin_strcmp (exp, target, mode)
if (TREE_SIDE_EFFECTS (len)) if (TREE_SIDE_EFFECTS (len))
return 0; return 0;
chainon (arglist, build_tree_list (NULL_TREE, len)); fn = built_in_decls[BUILT_IN_MEMCMP];
result = expand_builtin_memcmp (exp, arglist, target); if (!fn)
if (! result)
TREE_CHAIN (TREE_CHAIN (arglist)) = 0;
return result;
}
#else
return 0; return 0;
#endif
chainon (arglist, build_tree_list (NULL_TREE, len));
return expand_expr (build_function_call_expr (fn, arglist),
target, mode, EXPAND_NORMAL);
} }
/* Expand expression EXP, which is a call to the strncmp builtin. Return 0 /* Expand expression EXP, which is a call to the strncmp builtin. Return 0
...@@ -2390,6 +2452,7 @@ expand_builtin_strncmp (exp, target, mode) ...@@ -2390,6 +2452,7 @@ expand_builtin_strncmp (exp, target, mode)
enum machine_mode mode; enum machine_mode mode;
{ {
tree arglist = TREE_OPERAND (exp, 1); tree arglist = TREE_OPERAND (exp, 1);
tree fn, newarglist, len = 0;
tree arg1, arg2, arg3; tree arg1, arg2, arg3;
const char *p1, *p2; const char *p1, *p2;
...@@ -2442,13 +2505,9 @@ expand_builtin_strncmp (exp, target, mode) ...@@ -2442,13 +2505,9 @@ expand_builtin_strncmp (exp, target, mode)
return expand_expr (result, target, mode, EXPAND_NORMAL); return expand_expr (result, target, mode, EXPAND_NORMAL);
} }
#ifdef HAVE_cmpstrsi
/* If c_strlen can determine an expression for one of the string /* If c_strlen can determine an expression for one of the string
lengths, and it doesn't have side effects, then call lengths, and it doesn't have side effects, then call
expand_builtin_memcmp() using length MIN(strlen(string)+1, arg3). */ expand_builtin_memcmp() using length MIN(strlen(string)+1, arg3). */
if (HAVE_cmpstrsi)
{
tree newarglist, len = 0;
/* Perhaps one of the strings is really constant, if so prefer /* Perhaps one of the strings is really constant, if so prefer
that constant length over the other string's length. */ that constant length over the other string's length. */
...@@ -2467,6 +2526,10 @@ expand_builtin_strncmp (exp, target, mode) ...@@ -2467,6 +2526,10 @@ expand_builtin_strncmp (exp, target, mode)
if (!len) if (!len)
return 0; return 0;
fn = built_in_decls[BUILT_IN_MEMCMP];
if (!fn)
return 0;
/* Add one to the string length. */ /* Add one to the string length. */
len = fold (size_binop (PLUS_EXPR, len, ssize_int (1))); len = fold (size_binop (PLUS_EXPR, len, ssize_int (1)));
...@@ -2476,11 +2539,8 @@ expand_builtin_strncmp (exp, target, mode) ...@@ -2476,11 +2539,8 @@ expand_builtin_strncmp (exp, target, mode)
newarglist = build_tree_list (NULL_TREE, len); newarglist = build_tree_list (NULL_TREE, len);
newarglist = tree_cons (NULL_TREE, arg2, newarglist); newarglist = tree_cons (NULL_TREE, arg2, newarglist);
newarglist = tree_cons (NULL_TREE, arg1, newarglist); newarglist = tree_cons (NULL_TREE, arg1, newarglist);
return expand_builtin_memcmp (exp, newarglist, target); return expand_expr (build_function_call_expr (fn, newarglist),
} target, mode, EXPAND_NORMAL);
#endif
return 0;
} }
/* Expand expression EXP, which is a call to the strcat builtin. /* Expand expression EXP, which is a call to the strcat builtin.
...@@ -3661,7 +3721,7 @@ expand_builtin (exp, target, subtarget, mode, ignore) ...@@ -3661,7 +3721,7 @@ expand_builtin (exp, target, subtarget, mode, ignore)
break; break;
case BUILT_IN_STRCPY: case BUILT_IN_STRCPY:
target = expand_builtin_strcpy (exp); target = expand_builtin_strcpy (exp, target, mode);
if (target) if (target)
return target; return target;
break; break;
...@@ -3723,13 +3783,13 @@ expand_builtin (exp, target, subtarget, mode, ignore) ...@@ -3723,13 +3783,13 @@ expand_builtin (exp, target, subtarget, mode, ignore)
break; break;
case BUILT_IN_MEMCPY: case BUILT_IN_MEMCPY:
target = expand_builtin_memcpy (arglist); target = expand_builtin_memcpy (arglist, target, mode);
if (target) if (target)
return target; return target;
break; break;
case BUILT_IN_MEMSET: case BUILT_IN_MEMSET:
target = expand_builtin_memset (exp); target = expand_builtin_memset (exp, target, mode);
if (target) if (target)
return target; return target;
break; break;
...@@ -3752,21 +3812,12 @@ expand_builtin (exp, target, subtarget, mode, ignore) ...@@ -3752,21 +3812,12 @@ expand_builtin (exp, target, subtarget, mode, ignore)
return target; return target;
break; break;
/* These comparison functions need an instruction that returns an actual
index. An ordinary compare that just sets the condition codes
is not enough. */
#ifdef HAVE_cmpstrsi
case BUILT_IN_BCMP: case BUILT_IN_BCMP:
case BUILT_IN_MEMCMP: case BUILT_IN_MEMCMP:
target = expand_builtin_memcmp (exp, arglist, target); target = expand_builtin_memcmp (exp, arglist, target, mode);
if (target) if (target)
return target; return target;
break; break;
#else
case BUILT_IN_BCMP:
case BUILT_IN_MEMCMP:
break;
#endif
case BUILT_IN_SETJMP: case BUILT_IN_SETJMP:
target = expand_builtin_setjmp (arglist, target); target = expand_builtin_setjmp (arglist, target);
......
/* Copyright (C) 2001 Free Software Foundation.
Ensure builtin memset and memcpy are optimized away correctly.
Written by Roger Sayle, 11/23/2001. */
extern void abort (void);
typedef __SIZE_TYPE__ size_t;
extern void *memset (void *s, int c, size_t n);
extern void *memcpy (void *dest, const void *src, size_t n);
char dst[32];
char src[32];
int
main ()
{
memset (src, 0, 0);
memcpy (dst, src, 0);
return 0;
}
#ifdef __OPTIMIZE__
/* When optimizing, all the above cases should be transformed into
something else. So any remaining calls to the original function
should abort. */
static void *
memset (void *s, int c, size_t n)
{
abort ();
}
static void *
memcpy (void *dest, const void *src, size_t n)
{
abort ();
}
#endif
/* Copyright (C) 2001 Free Software Foundation.
Ensure that short builtin memcmp are optimized and perform correctly.
On architectures with a cmpstrsi instruction, this test doesn't determine
which optimization is being performed, but it does check for correctness.
Written by Roger Sayle, 12/02/2001. */
extern void abort (void);
typedef __SIZE_TYPE__ size_t;
extern int memcmp (const void *, const void *, size_t);
extern char *strcpy (char *, const char *);
int
main ()
{
char str[8];
strcpy (str, "3141");
if ( memcmp (str, str+2, 0) != 0 )
abort ();
if ( memcmp (str+1, str+3, 0) != 0 )
abort ();
if ( memcmp (str+1, str+3, 1) != 0 )
abort ();
if ( memcmp (str, str+2, 1) >= 0 )
abort ();
if ( memcmp (str+2, str, 1) <= 0 )
abort ();
return 0;
}
#ifdef __OPTIMIZE__
/* When optimizing, all the above cases should be transformed into
something else. So any remaining calls to the original function
should abort. */
static int
memcmp (const char *p1, const char *p2, size_t len)
{
abort ();
}
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment