This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: add h8sx support to h8300
On Jul 7, 2004, Richard Henderson <rth@redhat.com> wrote:
> On Wed, Jul 07, 2004 at 03:55:43AM -0300, Alexandre Oliva wrote:
>> However, even if it's close to stpcpy(), some arches will have the
>> final register point one-past the NUL terminator, whereas others might
>> have it point to the NUL terminator itself. I suppose we should
>> probably model movstr exactly after stpcpy(), even if that takes an
>> additional increment/decrement instruction to get the right value.
> Probably. With one output.
Is this sort of what you were expecting? Ok to install along with the
H8SX patch, if it passes a build&test cycle?
Index: builtins.c
===================================================================
RCS file: /cvs/uberbaum/gcc/builtins.c,v
retrieving revision 1.347
diff -u -p -d -u -p -d -u -p -r1.347 builtins.c
--- builtins.c 7 Jul 2004 19:23:54 -0000 1.347
+++ builtins.c 7 Jul 2004 23:05:47 -0000
@@ -2976,6 +2976,70 @@ expand_builtin_bcopy (tree arglist)
return expand_builtin_memmove (newarglist, const0_rtx, VOIDmode);
}
+/* Expand into a movstr instruction, if one is available. 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). If ENDP is 0 return the destination pointer, if ENDP
+ is 1 return the end pointer ala mempcpy, and if ENDP is 2 return
+ the end pointer minus one ala stpcpy. */
+
+static rtx
+expand_movstr (tree dest ATTRIBUTE_UNUSED,
+ tree src ATTRIBUTE_UNUSED,
+ rtx target ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ int endp ATTRIBUTE_UNUSED)
+{
+#ifndef HAVE_movstr
+ return 0;
+#else
+ rtx end;
+ rtx dest_mem;
+ rtx src_mem;
+ rtx insn;
+ const struct insn_data * data;
+
+ if (!HAVE_movstr)
+ return 0;
+
+ dest_mem = get_memory_rtx (dest);
+ src_mem = get_memory_rtx (src);
+ if (!endp)
+ {
+ XEXP (dest_mem, 0) = force_reg (Pmode, XEXP (dest_mem, 0));
+ target = XEXP (dest_mem, 0);
+ end = gen_reg_rtx (Pmode);
+ }
+ else
+ {
+ if (target == 0 || target == const0_rtx)
+ end = gen_reg_rtx (Pmode);
+ if (target == 0)
+ target = end;
+ }
+
+ data = insn_data + CODE_FOR_movstr;
+
+ if (data->operand[0].mode != VOIDmode)
+ end = gen_lowpart (data->operand[0].mode, end);
+
+ insn = data->genfun (end, dest_mem, src_mem);
+
+ if (insn == 0)
+ abort ();
+
+ emit_insn (insn);
+
+ /* movstr is supposed to set end to the address of the NUL
+ terminator. If the caller requested a mempcpy-like return value,
+ adjust it. */
+ if (endp == 1 && target != const0_rtx)
+ emit_move_insn (end, plus_constant (end, 1));
+
+ return target;
+#endif
+}
+
/* 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
@@ -2996,12 +3060,14 @@ expand_builtin_strcpy (tree arglist, rtx
if (operand_equal_p (src, dst, 0))
return expand_expr (dst, target, mode, EXPAND_NORMAL);
- fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
- if (!fn)
- return 0;
-
len = c_strlen (src, 1);
if (len == 0 || TREE_SIDE_EFFECTS (len))
+ return expand_movstr (TREE_VALUE (arglist),
+ TREE_VALUE (TREE_CHAIN (arglist)),
+ target, mode, /*endp=*/0);
+
+ fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
+ if (!fn)
return 0;
len = size_binop (PLUS_EXPR, len, ssize_int (1));
@@ -3020,30 +3086,25 @@ expand_builtin_strcpy (tree arglist, rtx
static rtx
expand_builtin_stpcpy (tree arglist, rtx target, enum machine_mode mode)
{
+ /* If return value is ignored, transform stpcpy into strcpy. */
+ if (target == const0_rtx)
+ return expand_builtin_strcpy (arglist, target, mode);
+
if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
else
{
tree dst, src, len;
- /* If return value is ignored, transform stpcpy into strcpy. */
- if (target == const0_rtx)
- {
- tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
- if (!fn)
- return 0;
-
- return expand_expr (build_function_call_expr (fn, arglist),
- target, mode, EXPAND_NORMAL);
- }
-
/* Ensure we get an actual string whose length can be evaluated at
compile-time, not an expression containing a string. This is
because the latter will potentially produce pessimized code
when used to produce the return value. */
src = TREE_VALUE (TREE_CHAIN (arglist));
if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
- return 0;
+ return expand_movstr (TREE_VALUE (arglist),
+ TREE_VALUE (TREE_CHAIN (arglist)),
+ target, mode, /*endp=*/2);
dst = TREE_VALUE (arglist);
len = fold (size_binop (PLUS_EXPR, len, ssize_int (1)));
--
Alexandre Oliva http://www.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist oliva@{lsd.ic.unicamp.br, gnu.org}