This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH]: Update patches for memset and memcmp builtins
- From: Roger Sayle <roger at eyesopen dot com>
- To: <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 10 Dec 2001 17:30:25 -0700 (MST)
- Subject: [PATCH]: Update patches for memset and memcmp builtins
Following Richard Kenner's patch to remove memory usage checking,
I'm resubmitting my two unreviewed patches to builtins.c against
the current mainline. Hopefully this should make them easier to
review.
Specifically, this patch revises the following patches:
Optimize builtin memset with length zero.
http://gcc.gnu.org/ml/gcc-patches/2001-11/msg01599.html
Optimize memcmp builtin for length zero or one.
http://gcc.gnu.org/ml/gcc-patches/2001-12/msg00295.html
For details, please refer to the above postings. This patch has
been bootstraped and checked on i686-pc-linux-gnu with no new
regressions.
2001-12-09 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.
* gcc.c-torture/execute/string-opt-14.c: New test case.
* gcc.c-torture/execute/string-opt-15.c: New test case.
*** gcc/gcc/builtins.c Sun Dec 9 11:26:56 2001
--- patch8/gcc/builtins.c Sun Dec 9 14:42:30 2001
*************** static rtx expand_builtin_next_arg PARAM
*** 101,109 ****
static rtx expand_builtin_va_start PARAMS ((int, tree));
static rtx expand_builtin_va_end PARAMS ((tree));
static rtx expand_builtin_va_copy PARAMS ((tree));
! #ifdef HAVE_cmpstrsi
! static rtx expand_builtin_memcmp PARAMS ((tree, tree, rtx));
! #endif
static rtx expand_builtin_strcmp PARAMS ((tree, rtx,
enum machine_mode));
static rtx expand_builtin_strncmp PARAMS ((tree, rtx,
--- 101,108 ----
static rtx expand_builtin_va_start PARAMS ((int, tree));
static rtx expand_builtin_va_end PARAMS ((tree));
static rtx expand_builtin_va_copy PARAMS ((tree));
! static rtx expand_builtin_memcmp PARAMS ((tree, tree, rtx,
! enum machine_mode));
static rtx expand_builtin_strcmp PARAMS ((tree, rtx,
enum machine_mode));
static rtx expand_builtin_strncmp PARAMS ((tree, rtx,
*************** static rtx expand_builtin_strspn PARAMS
*** 118,132 ****
enum machine_mode));
static rtx expand_builtin_strcspn PARAMS ((tree, rtx,
enum machine_mode));
! static rtx expand_builtin_memcpy PARAMS ((tree));
! static rtx expand_builtin_strcpy PARAMS ((tree));
static rtx builtin_strncpy_read_str PARAMS ((PTR, HOST_WIDE_INT,
enum machine_mode));
static rtx expand_builtin_strncpy PARAMS ((tree, rtx,
enum machine_mode));
static rtx builtin_memset_read_str PARAMS ((PTR, HOST_WIDE_INT,
enum machine_mode));
! static rtx expand_builtin_memset PARAMS ((tree));
static rtx expand_builtin_bzero PARAMS ((tree));
static rtx expand_builtin_strlen PARAMS ((tree, rtx));
static rtx expand_builtin_strstr PARAMS ((tree, rtx,
--- 117,134 ----
enum machine_mode));
static rtx expand_builtin_strcspn PARAMS ((tree, rtx,
enum machine_mode));
! static rtx expand_builtin_memcpy PARAMS ((tree, rtx,
! 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,
enum machine_mode));
static rtx expand_builtin_strncpy PARAMS ((tree, rtx,
enum machine_mode));
static rtx builtin_memset_read_str PARAMS ((PTR, HOST_WIDE_INT,
enum machine_mode));
! static rtx expand_builtin_memset PARAMS ((tree, rtx,
! enum machine_mode));
static rtx expand_builtin_bzero PARAMS ((tree));
static rtx expand_builtin_strlen PARAMS ((tree, rtx));
static rtx expand_builtin_strstr PARAMS ((tree, rtx,
*************** builtin_memcpy_read_str (data, offset, m
*** 1910,1920 ****
return c_readstr (str + offset, mode);
}
! /* Expand a call to the memcpy builtin, with arguments in ARGLIST. */
static rtx
! expand_builtin_memcpy (arglist)
tree arglist;
{
if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
--- 1912,1927 ----
return c_readstr (str + offset, mode);
}
! /* 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
! expand_builtin_memcpy (arglist, target, mode)
tree arglist;
+ rtx target;
+ enum machine_mode mode;
{
if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
*************** expand_builtin_memcpy (arglist)
*** 1931,1940 ****
= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
rtx dest_mem, src_mem, dest_addr, len_rtx;
! /* If either SRC or DEST is not a pointer type, don't do
! this operation in-line. */
! if (src_align == 0 || dest_align == 0)
! return 0;
dest_mem = get_memory_rtx (dest);
set_mem_align (dest_mem, dest_align);
--- 1938,1959 ----
= get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
rtx dest_mem, src_mem, dest_addr, len_rtx;
! /* If DEST is not a pointer type, call the normal function. */
! if (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;
dest_mem = get_memory_rtx (dest);
set_mem_align (dest_mem, dest_align);
*************** expand_builtin_memcpy (arglist)
*** 1970,2002 ****
}
/* Expand expression EXP, which is a call to the strcpy builtin. Return 0
! if we failed the caller should emit a normal call. */
static rtx
! expand_builtin_strcpy (exp)
tree exp;
{
tree arglist = TREE_OPERAND (exp, 1);
! rtx result;
if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
- else
- {
- tree len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
-
- if (len == 0)
- return 0;
! len = size_binop (PLUS_EXPR, len, ssize_int (1));
! chainon (arglist, build_tree_list (NULL_TREE, len));
! }
! 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)
--- 1989,2022 ----
}
/* Expand expression EXP, which is a call to the strcpy builtin. 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
! expand_builtin_strcpy (exp, target, mode)
tree exp;
+ rtx target;
+ enum machine_mode mode;
{
tree arglist = TREE_OPERAND (exp, 1);
! tree fn, len;
if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
! fn = built_in_decls[BUILT_IN_MEMCPY];
! if (!fn)
! return 0;
! len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
! if (len == 0)
! return 0;
! len = size_binop (PLUS_EXPR, len, ssize_int (1));
! chainon (arglist, build_tree_list (NULL_TREE, len));
! return expand_expr (build_function_call_expr (fn, arglist),
! target, mode, EXPAND_NORMAL);
}
/* Callback routine for store_by_pieces. Read GET_MODE_BITSIZE (MODE)
*************** expand_builtin_strncpy (arglist, target,
*** 2033,2038 ****
--- 2053,2059 ----
{
tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
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)
*************** expand_builtin_strncpy (arglist, target,
*** 2081,2087 ****
}
/* OK transform into builtin memcpy. */
! return expand_builtin_memcpy (arglist);
}
}
--- 2102,2112 ----
}
/* OK transform into builtin memcpy. */
! fn = built_in_decls[BUILT_IN_MEMCPY];
! if (!fn)
! return 0;
! return expand_expr (build_function_call_expr (fn, arglist),
! target, mode, EXPAND_NORMAL);
}
}
*************** builtin_memset_read_str (data, offset, m
*** 2104,2114 ****
}
/* Expand expression EXP, which is a call to the memset builtin. Return 0
! if we failed the caller should emit a normal call. */
!
static rtx
! expand_builtin_memset (exp)
tree exp;
{
tree arglist = TREE_OPERAND (exp, 1);
--- 2129,2143 ----
}
/* Expand expression EXP, which is a call to the memset builtin. 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
! expand_builtin_memset (exp, target, mode)
tree exp;
+ rtx target;
+ enum machine_mode mode;
{
tree arglist = TREE_OPERAND (exp, 1);
*************** expand_builtin_memset (exp)
*** 2131,2136 ****
--- 2160,2174 ----
if (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 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)
return 0;
*************** expand_builtin_bzero (exp)
*** 2184,2226 ****
size = TREE_VALUE (TREE_CHAIN (arglist));
/* New argument list transforming bzero(ptr x, int y) to
! memset(ptr x, int 0, size_t y). */
!
newarglist = build_tree_list (NULL_TREE, convert (sizetype, size));
newarglist = tree_cons (NULL_TREE, integer_zero_node, newarglist);
newarglist = tree_cons (NULL_TREE, dest, newarglist);
TREE_OPERAND (exp, 1) = newarglist;
! result = expand_builtin_memset(exp);
!
/* Always restore the original arguments. */
TREE_OPERAND (exp, 1) = arglist;
return result;
}
- #ifdef HAVE_cmpstrsi
-
/* 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
caller should emit a normal call, otherwise try to get the result in
! TARGET, if convenient. */
static rtx
! expand_builtin_memcmp (exp, arglist, target)
tree exp;
tree arglist;
rtx target;
{
if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
{
- 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 result;
rtx insn;
--- 2222,2296 ----
size = TREE_VALUE (TREE_CHAIN (arglist));
/* New argument list transforming bzero(ptr x, int y) to
! 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 = tree_cons (NULL_TREE, integer_zero_node, newarglist);
newarglist = tree_cons (NULL_TREE, dest, newarglist);
TREE_OPERAND (exp, 1) = newarglist;
! result = expand_builtin_memset (exp, const0_rtx, VOIDmode);
!
/* Always restore the original arguments. */
TREE_OPERAND (exp, 1) = arglist;
return result;
}
/* 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
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
! expand_builtin_memcmp (exp, arglist, target, mode)
tree exp;
tree arglist;
rtx target;
+ enum machine_mode mode;
{
+ tree arg1, arg2, len;
+
if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
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
{
rtx arg1_rtx, arg2_rtx, arg3_rtx;
rtx result;
rtx insn;
*************** expand_builtin_memcmp (exp, arglist, tar
*** 2275,2282 ****
else
return convert_to_mode (mode, result, 0);
}
! }
#endif
/* 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
--- 2345,2354 ----
else
return convert_to_mode (mode, result, 0);
}
! #else
! return 0;
#endif
+ }
/* 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
*************** expand_builtin_strcmp (exp, target, mode
*** 2289,2295 ****
enum machine_mode mode;
{
tree arglist = TREE_OPERAND (exp, 1);
! tree arg1, arg2;
const char *p1, *p2;
if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
--- 2361,2367 ----
enum machine_mode mode;
{
tree arglist = TREE_OPERAND (exp, 1);
! tree arg1, arg2, len, len2, fn;
const char *p1, *p2;
if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
*************** expand_builtin_strcmp (exp, target, mode
*** 2325,2382 ****
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
! #ifdef HAVE_cmpstrsi
! if (! HAVE_cmpstrsi)
! return 0;
! {
! tree len = c_strlen (arg1);
! tree len2 = c_strlen (arg2);
! rtx result;
! if (len)
! len = size_binop (PLUS_EXPR, ssize_int (1), len);
! if (len2)
! len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
! /* If we don't have a constant length for the first, use the length
! of the second, if we know it. We don't require a constant for
! this case; some cost analysis could be done if both are available
! but neither is constant. For now, assume they're equally cheap
! unless one has side effects.
!
! If both strings have constant lengths, use the smaller. This
! could arise if optimization results in strcpy being called with
! two fixed strings, or if the code was machine-generated. We should
! add some code to the `memcmp' handler below to deal with such
! situations, someday. */
! if (!len || TREE_CODE (len) != INTEGER_CST)
! {
! if (len2 && !TREE_SIDE_EFFECTS (len2))
! len = len2;
! else if (len == 0)
! return 0;
! }
! else if (len2 && TREE_CODE (len2) == INTEGER_CST
! && tree_int_cst_lt (len2, len))
! len = len2;
! /* If both arguments have side effects, we cannot optimize. */
! if (TREE_SIDE_EFFECTS (len))
! return 0;
! chainon (arglist, build_tree_list (NULL_TREE, len));
! result = expand_builtin_memcmp (exp, arglist, target);
! if (! result)
! TREE_CHAIN (TREE_CHAIN (arglist)) = 0;
! return result;
! }
! #else
! return 0;
! #endif
}
/* Expand expression EXP, which is a call to the strncmp builtin. Return 0
--- 2397,2445 ----
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
! len = c_strlen (arg1);
! len2 = c_strlen (arg2);
! if (len)
! len = size_binop (PLUS_EXPR, ssize_int (1), len);
! if (len2)
! len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
! /* If we don't have a constant length for the first, use the length
! of the second, if we know it. We don't require a constant for
! this case; some cost analysis could be done if both are available
! but neither is constant. For now, assume they're equally cheap
! unless one has side effects.
! If both strings have constant lengths, use the smaller. This
! could arise if optimization results in strcpy being called with
! two fixed strings, or if the code was machine-generated. We should
! add some code to the `memcmp' handler below to deal with such
! situations, someday. */
! if (!len || TREE_CODE (len) != INTEGER_CST)
! {
! if (len2 && !TREE_SIDE_EFFECTS (len2))
! len = len2;
! else if (len == 0)
! return 0;
! }
! else if (len2 && TREE_CODE (len2) == INTEGER_CST
! && tree_int_cst_lt (len2, len))
! len = len2;
! /* If both arguments have side effects, we cannot optimize. */
! if (TREE_SIDE_EFFECTS (len))
! return 0;
! fn = built_in_decls[BUILT_IN_MEMCMP];
! if (!fn)
! return 0;
! 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_builtin_strncmp (exp, target, mod
*** 2390,2395 ****
--- 2453,2459 ----
enum machine_mode mode;
{
tree arglist = TREE_OPERAND (exp, 1);
+ tree fn, newarglist, len = 0;
tree arg1, arg2, arg3;
const char *p1, *p2;
*************** expand_builtin_strncmp (exp, target, mod
*** 2442,2486 ****
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
- #ifdef HAVE_cmpstrsi
/* If c_strlen can determine an expression for one of the string
lengths, and it doesn't have side effects, then call
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
! that constant length over the other string's length. */
! if (p1)
! len = c_strlen (arg1);
! else if (p2)
! len = c_strlen (arg2);
!
! /* If we still don't have a len, try either string arg as long
! as they don't have side effects. */
! if (!len && !TREE_SIDE_EFFECTS (arg1))
! len = c_strlen (arg1);
! if (!len && !TREE_SIDE_EFFECTS (arg2))
! len = c_strlen (arg2);
! /* If we still don't have a length, punt. */
! if (!len)
! return 0;
!
! /* Add one to the string length. */
! len = fold (size_binop (PLUS_EXPR, len, ssize_int (1)));
! /* The actual new length parameter is MIN(len,arg3). */
! len = fold (build (MIN_EXPR, TREE_TYPE (len), len, arg3));
! newarglist = build_tree_list (NULL_TREE, len);
! newarglist = tree_cons (NULL_TREE, arg2, newarglist);
! newarglist = tree_cons (NULL_TREE, arg1, newarglist);
! return expand_builtin_memcmp (exp, newarglist, target);
! }
! #endif
!
! return 0;
}
/* Expand expression EXP, which is a call to the strcat builtin.
--- 2506,2547 ----
return expand_expr (result, target, mode, EXPAND_NORMAL);
}
/* If c_strlen can determine an expression for one of the string
lengths, and it doesn't have side effects, then call
expand_builtin_memcmp() using length MIN(strlen(string)+1, arg3). */
!
! /* Perhaps one of the strings is really constant, if so prefer
! that constant length over the other string's length. */
! if (p1)
! len = c_strlen (arg1);
! else if (p2)
! len = c_strlen (arg2);
!
! /* If we still don't have a len, try either string arg as long
! as they don't have side effects. */
! if (!len && !TREE_SIDE_EFFECTS (arg1))
! len = c_strlen (arg1);
! if (!len && !TREE_SIDE_EFFECTS (arg2))
! len = c_strlen (arg2);
! /* If we still don't have a length, punt. */
! if (!len)
! return 0;
!
! fn = built_in_decls[BUILT_IN_MEMCMP];
! if (!fn)
! return 0;
!
! /* Add one to the string length. */
! len = fold (size_binop (PLUS_EXPR, len, ssize_int (1)));
! /* The actual new length parameter is MIN(len,arg3). */
! len = fold (build (MIN_EXPR, TREE_TYPE (len), len, arg3));
! newarglist = build_tree_list (NULL_TREE, len);
! newarglist = tree_cons (NULL_TREE, arg2, newarglist);
! newarglist = tree_cons (NULL_TREE, arg1, newarglist);
! return expand_expr (build_function_call_expr (fn, newarglist),
! target, mode, EXPAND_NORMAL);
}
/* Expand expression EXP, which is a call to the strcat builtin.
*************** expand_builtin (exp, target, subtarget,
*** 3639,3645 ****
break;
case BUILT_IN_STRCPY:
! target = expand_builtin_strcpy (exp);
if (target)
return target;
break;
--- 3700,3706 ----
break;
case BUILT_IN_STRCPY:
! target = expand_builtin_strcpy (exp, target, mode);
if (target)
return target;
break;
*************** expand_builtin (exp, target, subtarget,
*** 3701,3713 ****
break;
case BUILT_IN_MEMCPY:
! target = expand_builtin_memcpy (arglist);
if (target)
return target;
break;
case BUILT_IN_MEMSET:
! target = expand_builtin_memset (exp);
if (target)
return target;
break;
--- 3762,3774 ----
break;
case BUILT_IN_MEMCPY:
! target = expand_builtin_memcpy (arglist, target, mode);
if (target)
return target;
break;
case BUILT_IN_MEMSET:
! target = expand_builtin_memset (exp, target, mode);
if (target)
return target;
break;
*************** expand_builtin (exp, target, subtarget,
*** 3730,3750 ****
return target;
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_MEMCMP:
! target = expand_builtin_memcmp (exp, arglist, target);
if (target)
return target;
break;
- #else
- case BUILT_IN_BCMP:
- case BUILT_IN_MEMCMP:
- break;
- #endif
case BUILT_IN_SETJMP:
target = expand_builtin_setjmp (arglist, target);
--- 3791,3802 ----
return target;
break;
case BUILT_IN_BCMP:
case BUILT_IN_MEMCMP:
! target = expand_builtin_memcmp (exp, arglist, target, mode);
if (target)
return target;
break;
case BUILT_IN_SETJMP:
target = expand_builtin_setjmp (arglist, target);
*** /dev/null Tue May 5 14:32:27 1998
--- string-opt-14.c Sun Dec 9 13:42:54 2001
***************
*** 0 ****
--- 1,40 ----
+ /* 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
+
*** /dev/null Tue May 5 14:32:27 1998
--- string-opt-15.c Mon Dec 3 14:21:38 2001
***************
*** 0 ****
--- 1,46 ----
+ /* 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
+
Roger
--
Roger Sayle, E-mail: roger@eyesopen.com
OpenEye Scientific Software, WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road, Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507. Fax: (+1) 505-438-3470