This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: add h8sx support to h8300


On Jul  7, 2004, Richard Henderson <rth@redhat.com> wrote:

> On Wed, Jul 07, 2004 at 08:07:24PM -0300, Alexandre Oliva wrote:
>> +#ifndef HAVE_movstr
>> +  return 0;
>> +#else

> One change; please do the macro frobbing to avoid the conditional
> compilation.

Doh, I hadn't found precedent for defaulting CODE_FOR_<insn> before.

How about this?  I fixed a bug of uninitialized `end' and added more
cases to expand_builtin_stpcpy() to get strcpy and stpcpy inlined in
all cases for the attached testcase, compiled with -O3.

How's this patchlet?

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	8 Jul 2004 01:05:29 -0000
@@ -2976,6 +2976,72 @@ expand_builtin_bcopy (tree arglist)
   return expand_builtin_memmove (newarglist, const0_rtx, VOIDmode);
 }
 
+#ifndef HAVE_movstr
+# define HAVE_movstr 0
+# define CODE_FOR_movstr CODE_FOR_nothing
+#endif
+
+/* 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, tree src, rtx target,
+	       enum machine_mode mode, int endp)
+{
+  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;
+	}
+      else
+	end = target;
+    }
+
+  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;
+}
+
 /* 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 +3062,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,22 +3088,17 @@ 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);
-	}
+      tree narglist;
+      rtx ret;
 
       /* Ensure we get an actual string whose length can be evaluated at
          compile-time, not an expression containing a string.  This is
@@ -3043,14 +3106,46 @@ expand_builtin_stpcpy (tree arglist, rtx
          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)));
-      arglist = build_tree_list (NULL_TREE, len);
-      arglist = tree_cons (NULL_TREE, src, arglist);
-      arglist = tree_cons (NULL_TREE, dst, arglist);
-      return expand_builtin_mempcpy (arglist, target, mode, /*endp=*/2);
+      narglist = build_tree_list (NULL_TREE, len);
+      narglist = tree_cons (NULL_TREE, src, narglist);
+      narglist = tree_cons (NULL_TREE, dst, narglist);
+      ret = expand_builtin_mempcpy (narglist, target, mode, /*endp=*/2);
+
+      if (ret)
+	return ret;
+
+      if (TREE_CODE (len) == INTEGER_CST)
+	{
+	  rtx len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
+
+	  if (GET_CODE (len_rtx) == CONST_INT)
+	    {
+	      ret = expand_builtin_strcpy (arglist, target, mode);
+
+	      if (ret)
+		{
+		  target = ret;
+
+		  ret = emit_move_insn (target,
+					plus_constant (target,
+						       INTVAL (len_rtx)));
+		  if (! ret)
+		    abort ();
+
+		  return target;
+		}
+	    }
+	}
+
+      return expand_movstr (TREE_VALUE (arglist),
+			    TREE_VALUE (TREE_CHAIN (arglist)),
+			    target, mode, /*endp=*/2);
     }
 }
 

 

char *copy(char *dest, const char *src) {
  return strcpy(dest, src);
}

char *copy2(char *dest, const char *src) {
  return stpcpy(dest, src);
}

char *copy3(char *dest) {
  return copy(dest, "this is a test");
}

char *copy4(char *dest) {
  return copy2(dest, "this is a test");
}

void copy5(char *dest) {
  copy3(dest);
}

void copy6(char *dest) {
  copy4(dest);
}
-- 
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}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]