This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [patch] use movstr in strcat
- From: Adrian Straetling <straetling at de dot ibm dot com>
- To: Richard Henderson <rth at redhat dot com>, gcc-patches at gcc dot gnu dot org, uweigand at de dot ibm dot com, krebbel1 at de dot ibm dot com
- Date: Thu, 25 Aug 2005 23:29:28 +0200
- Subject: Re: [patch] use movstr in strcat
- References: <20050825111218.GA24668@de.ibm.com> <20050825174626.GB8285@redhat.com>
On Thu, Aug 25, 2005 at 10:46:26AM -0700, Richard Henderson wrote:
> On Thu, Aug 25, 2005 at 01:12:18PM +0200, Adrian Straetling wrote:
> > * builtins.c: (expand_builtin_strcat): Add support for
> > expand_movstr.
>
> You're duplicating a lot of code here. It seems to me the best
> way to approach this is to start a sequence, build the strlen
> addition, and then defer to expand_builtin_strcpy. If the
> expansion of the strcpy fails, abort the sequence. You may have
> to play games like in expand_builtin_mathfn_2 in order to reliably
> stabilize the arguments.
Thank you for the quick review and pointing at the right place to look at.
You'll find updated patch below.
I've changed the prototype of expand_builtin_strcpy to avoid the packing and
unpacking of exp.
A quick test showed no problems with builtin.exp, bootstrap is currently running.
I'll repost the patch with a changelog tomorrow if testing looks fine and there
are no other objections.
regards,
Adrian
Index: gcc/builtins.c
===================================================================
*** gcc/builtins.c.orig 2005-08-24 09:34:50.000000000 +0200
--- gcc/builtins.c 2005-08-25 23:02:57.000000000 +0200
*************** static rtx expand_builtin_memcpy (tree,
*** 113,119 ****
static rtx expand_builtin_mempcpy (tree, tree, rtx, enum machine_mode, int);
static rtx expand_builtin_memmove (tree, tree, rtx, enum machine_mode, tree);
static rtx expand_builtin_bcopy (tree);
! static rtx expand_builtin_strcpy (tree, rtx, enum machine_mode);
static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
static rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode);
--- 113,119 ----
static rtx expand_builtin_mempcpy (tree, tree, rtx, enum machine_mode, int);
static rtx expand_builtin_memmove (tree, tree, rtx, enum machine_mode, tree);
static rtx expand_builtin_bcopy (tree);
! static rtx expand_builtin_strcpy (tree, tree, rtx, enum machine_mode);
static rtx expand_builtin_stpcpy (tree, rtx, enum machine_mode);
static rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
static rtx expand_builtin_strncpy (tree, rtx, enum machine_mode);
*************** expand_movstr (tree dest, tree src, rtx
*** 3087,3096 ****
convenient). */
static rtx
! expand_builtin_strcpy (tree exp, rtx target, enum machine_mode mode)
{
- tree fndecl = get_callee_fndecl (exp);
- tree arglist = TREE_OPERAND (exp, 1);
if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
{
tree result = fold_builtin_strcpy (fndecl, arglist, 0);
--- 3087,3094 ----
convenient). */
static rtx
! expand_builtin_strcpy (tree fndecl, tree arglist, rtx target, enum machine_mode mode)
{
if (validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
{
tree result = fold_builtin_strcpy (fndecl, arglist, 0);
*************** expand_builtin_stpcpy (tree exp, rtx tar
*** 3159,3165 ****
if (GET_CODE (len_rtx) == CONST_INT)
{
! ret = expand_builtin_strcpy (exp, target, mode);
if (ret)
{
--- 3157,3164 ----
if (GET_CODE (len_rtx) == CONST_INT)
{
! ret = expand_builtin_strcpy (get_callee_fndecl (exp),
! arglist, target, mode);
if (ret)
{
*************** expand_builtin_strncmp (tree exp, rtx ta
*** 3825,3885 ****
otherwise try to get the result in TARGET, if convenient. */
static rtx
! 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;
else
{
tree dst = TREE_VALUE (arglist),
! src = TREE_VALUE (TREE_CHAIN (arglist));
const char *p = c_getstr (src);
! if (p)
{
! /* If the string length is zero, return the dst parameter. */
! if (*p == '\0')
! return expand_expr (dst, target, mode, EXPAND_NORMAL);
! else if (!optimize_size)
! {
! /* Otherwise if !optimize_size, see if we can store by
! pieces into (dst + strlen(dst)). */
! tree newdst, arglist,
! strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
!
! /* This is the length argument. */
! arglist = build_tree_list (NULL_TREE,
! fold (size_binop (PLUS_EXPR,
! c_strlen (src, 0),
! ssize_int (1))));
! /* Prepend src argument. */
! arglist = tree_cons (NULL_TREE, src, arglist);
! /* We're going to use dst more than once. */
! dst = builtin_save_expr (dst);
! /* Create strlen (dst). */
! newdst =
! build_function_call_expr (strlen_fn,
! build_tree_list (NULL_TREE, dst));
! /* Create (dst + (cast) strlen (dst)). */
! newdst = fold_convert (TREE_TYPE (dst), newdst);
! newdst = fold_build2 (PLUS_EXPR, TREE_TYPE (dst), dst, newdst);
!
! /* Prepend the new dst argument. */
! arglist = tree_cons (NULL_TREE, newdst, arglist);
!
! /* We don't want to get turned into a memcpy if the
! target is const0_rtx, i.e. when the return value
! isn't used. That would produce pessimized code so
! 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, type, /*target=*/0, mode, /*endp=*/0))
! return expand_expr (dst, target, mode, EXPAND_NORMAL);
! else
! return 0;
}
}
return 0;
--- 3824,3884 ----
otherwise try to get the result in TARGET, if convenient. */
static rtx
! expand_builtin_strcat (tree fndecl, tree arglist, rtx target, enum machine_mode mode)
{
if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
else
{
tree dst = TREE_VALUE (arglist),
! src = TREE_VALUE (TREE_CHAIN (arglist));
const char *p = c_getstr (src);
! /* If the string length is zero, return the dst parameter. */
! if (p && *p == '\0')
! return expand_expr (dst, target, mode, EXPAND_NORMAL);
!
! if (!optimize_size)
{
! /* See if we can store by pieces into (dst + strlen(dst)). */
! tree newsrc, newdst,
! strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
! rtx insns;
!
! /* Stabilize the argument list. */
! newsrc = builtin_save_expr (src);
! if (newsrc != src)
! arglist = build_tree_list (NULL_TREE, newsrc);
! else
! arglist = TREE_CHAIN (arglist); /* Reusing arglist if safe. */
!
! dst = builtin_save_expr (dst);
!
! start_sequence ();
!
! /* Create strlen (dst). */
! newdst =
! build_function_call_expr (strlen_fn,
! build_tree_list (NULL_TREE, dst));
! /* Create (dst + (cast) strlen (dst)). */
! newdst = fold_convert (TREE_TYPE (dst), newdst);
! newdst = fold_build2 (PLUS_EXPR, TREE_TYPE (dst), dst, newdst);
! newdst = builtin_save_expr (newdst);
! arglist = tree_cons (NULL_TREE, newdst, arglist);
! if (!expand_builtin_strcpy (fndecl, arglist, target, mode))
! {
! end_sequence (); /* Stop sequence. */
! return 0;
}
+
+ /* Output the entire sequence. */
+ insns = get_insns ();
+ end_sequence ();
+ emit_insn (insns);
+
+ return expand_expr (dst, target, mode, EXPAND_NORMAL);
}
return 0;
*************** expand_builtin (tree exp, rtx target, rt
*** 5828,5834 ****
break;
case BUILT_IN_STRCPY:
! target = expand_builtin_strcpy (exp, target, mode);
if (target)
return target;
break;
--- 5827,5833 ----
break;
case BUILT_IN_STRCPY:
! target = expand_builtin_strcpy (fndecl, arglist, target, mode);
if (target)
return target;
break;
*************** expand_builtin (tree exp, rtx target, rt
*** 5846,5852 ****
break;
case BUILT_IN_STRCAT:
! target = expand_builtin_strcat (arglist, TREE_TYPE (exp), target, mode);
if (target)
return target;
break;
--- 5845,5851 ----
break;
case BUILT_IN_STRCAT:
! target = expand_builtin_strcat (fndecl, arglist, target, mode);
if (target)
return target;
break;