builtins.c (target_char_cast): New function.
authorJakub Jelinek <jakub@redhat.com>
Fri, 1 Dec 2000 17:53:07 +0000 (18:53 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 1 Dec 2000 17:53:07 +0000 (18:53 +0100)
* builtins.c (target_char_cast): New function.
(expand_builtin_strchr): Use it.
(expand_builtin_strrchr): Use it.
(builtin_memset_read_str): New function.
(expand_builtin_memset): Use target_char_cast.
Try to optimize memset with second argument non-zero using
store_by_pieces.

* gcc.c-torture/execute/string-opt-5.c: Add some memset tests.

From-SVN: r37918

gcc/ChangeLog
gcc/builtins.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/string-opt-5.c

index 86643d0cff4a84ff68bee8891dad38784381ae31..024d701da75b9e55fa2db07f82496100b6ba5977 100644 (file)
@@ -1,3 +1,13 @@
+2000-12-01  Jakub Jelinek  <jakub@redhat.com>
+
+       * builtins.c (target_char_cast): New function.
+       (expand_builtin_strchr): Use it.
+       (expand_builtin_strrchr): Use it.
+       (builtin_memset_read_str): New function.
+       (expand_builtin_memset): Use target_char_cast.
+       Try to optimize memset with second argument non-zero using
+       store_by_pieces.
+
 2000-11-30  Marek Michalkiewicz  <marekm@linux.org.pl>
 
        * install.texi (avr): Replace incomplete list of supported MCU
index 07d10adf446bc7e7fa477ab57d2a71e16939fd4e..0e59904325e50676e0f8e8890de61729a4b4de7e 100644 (file)
@@ -83,6 +83,7 @@ static tree c_strlen                  PARAMS ((tree));
 static const char *c_getstr            PARAMS ((tree));
 static rtx c_readstr                   PARAMS ((const char *,
                                                 enum machine_mode));
+static int target_char_cast            PARAMS ((tree, char *)); 
 static rtx get_memory_rtx              PARAMS ((tree));
 static int apply_args_size             PARAMS ((void));
 static int apply_result_size           PARAMS ((void));
@@ -116,6 +117,8 @@ 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));
@@ -317,6 +320,7 @@ c_getstr (src)
 /* Return a CONST_INT or CONST_DOUBLE corresponding to target
    reading GET_MODE_BITSIZE (MODE) bits from string constant
    STR.  */
+
 static rtx
 c_readstr (str, mode)
      const char *str;
@@ -349,6 +353,36 @@ c_readstr (str, mode)
   return immed_double_const (c[0], c[1], mode);
 }
 
+/* Cast a target constant CST to target CHAR and if that value fits into
+   host char type, return zero and put that value into variable pointed by
+   P.  */
+
+static int
+target_char_cast (cst, p)
+     tree cst;
+     char *p;
+{
+  unsigned HOST_WIDE_INT val, hostval;
+
+  if (TREE_CODE (cst) != INTEGER_CST
+      || CHAR_TYPE_SIZE > HOST_BITS_PER_WIDE_INT)
+    return 1;
+
+  val = TREE_INT_CST_LOW (cst);
+  if (CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT)
+    val &= (((unsigned HOST_WIDE_INT) 1) << CHAR_TYPE_SIZE) - 1;
+
+  hostval = val;
+  if (HOST_BITS_PER_CHAR < HOST_BITS_PER_WIDE_INT)
+    hostval &= (((unsigned HOST_WIDE_INT) 1) << HOST_BITS_PER_CHAR) - 1;
+
+  if (val != hostval)
+    return 1;
+
+  *p = hostval;
+  return 0;
+}
+
 /* Given TEM, a pointer to a stack frame, follow the dynamic chain COUNT
    times to get the address of either a higher stack frame, or a return
    address located within it (depending on FNDECL_CODE).  */
@@ -1583,7 +1617,13 @@ expand_builtin_strchr (arglist, target, mode)
       p1 = c_getstr (s1);
       if (p1 != NULL)
        {
-         const char *r = strchr (p1, (char) TREE_INT_CST_LOW (s2));
+         char c;
+         const char *r;
+
+         if (target_char_cast (s2, &c))
+           return 0;
+
+         r = strchr (p1, c);
 
          if (r == NULL)
            return const0_rtx;
@@ -1628,7 +1668,13 @@ expand_builtin_strrchr (arglist, target, mode)
       p1 = c_getstr (s1);
       if (p1 != NULL)
        {
-         const char *r = strrchr (p1, (char) TREE_INT_CST_LOW (s2));
+         char c;
+         const char *r;
+
+         if (target_char_cast (s2, &c))
+           return 0;
+
+         r = strrchr (p1, c);
 
          if (r == NULL)
            return const0_rtx;
@@ -1945,6 +1991,24 @@ expand_builtin_strncpy (arglist, target, mode)
     }
 }
 
+/* Callback routine for store_by_pieces.  Read GET_MODE_BITSIZE (MODE)
+   bytes from constant string DATA + OFFSET and return it as target
+   constant.  */
+
+static rtx
+builtin_memset_read_str (data, offset, mode)
+     PTR data;
+     HOST_WIDE_INT offset ATTRIBUTE_UNUSED;
+     enum machine_mode mode;
+{
+  const char *c = (const char *) data;
+  char *p = alloca (GET_MODE_SIZE (mode));
+
+  memset (p, *c, GET_MODE_SIZE (mode));
+
+  return c_readstr (p, mode);
+}
+
 /* Expand expression EXP, which is a call to the memset builtin.  Return 0
    if we failed the caller should emit a normal call.  */
 
@@ -1971,6 +2035,7 @@ expand_builtin_memset (exp)
       tree dest = TREE_VALUE (arglist);
       tree val = TREE_VALUE (TREE_CHAIN (arglist));
       tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+      char c;
 
       int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
       rtx dest_mem, dest_addr, len_rtx;
@@ -1980,19 +2045,29 @@ expand_builtin_memset (exp)
       if (dest_align == 0)
        return 0;
 
-      /* If the arguments have side-effects, then we can only evaluate
-        them at most once.  The following code evaluates them twice if
-        they are not constants because we break out to expand_call
-        in that case.  They can't be constants if they have side-effects
-        so we can check for that first.  Alternatively, we could call
-        save_expr to make multiple evaluation safe.  */
-      if (TREE_SIDE_EFFECTS (val) || TREE_SIDE_EFFECTS (len))
+      if (TREE_CODE (val) != INTEGER_CST)
        return 0;
 
-      /* If VAL is not 0, don't do this operation in-line. */
-      if (expand_expr (val, NULL_RTX, VOIDmode, 0) != const0_rtx)
+      if (target_char_cast (val, &c))
        return 0;
 
+      if (c)
+       {
+         if (TREE_CODE (len) != INTEGER_CST || TREE_INT_CST_HIGH (len))
+           return 0;
+         if (current_function_check_memory_usage
+             || !can_store_by_pieces (TREE_INT_CST_LOW (len),
+                                      builtin_memset_read_str,
+                                      (PTR) &c, dest_align))
+           return 0;
+
+         dest_mem = get_memory_rtx (dest);
+         store_by_pieces (dest_mem, TREE_INT_CST_LOW (len),
+                          builtin_memset_read_str,
+                          (PTR) &c, dest_align);
+         return force_operand (XEXP (dest_mem, 0), NULL_RTX);
+       }
+
       len_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
 
       dest_mem = get_memory_rtx (dest);
index aae082d791f1b90111a6d0f6cc4d51efc74dfc75..4b7d5fba4968164b550fdbbe6cae8b86f3f04226 100644 (file)
@@ -1,3 +1,7 @@
+2000-12-01  Jakub Jelinek  <jakub@redhat.com>
+
+       * gcc.c-torture/execute/string-opt-5.c: Add some memset tests.
+
 2000-12-01  Nathan Sidwell  <nathan@codesourcery.com>
 
        * g++.old-deja/g++.other/cast6.C: New test.
index 108c3ed4773889d7efdbb187bfee8824bae7f703..178812226dc390d087abdebca1b7013b285ae72c 100644 (file)
@@ -17,6 +17,7 @@ extern int memcmp (const void *, const void *, __SIZE_TYPE__);
 int x = 6;
 int y = 1;
 char *bar = "hi world";
+char buf [64];
 
 int main()
 {
@@ -79,7 +80,28 @@ int main()
     abort ();
   memset (dst, ' ', sizeof dst);
   if (strncpy (dst, "hello", 8) != dst || memcmp (dst, "hello\0\0\0 ", 9))
-    abort();
+    abort ();
+  x = '!';
+  memset (buf, ' ', sizeof buf);
+  if (memset (buf, x++, ++y) != buf
+      || x != '!' + 1
+      || y != 3
+      || memcmp (buf, "!!!", 3))
+    abort ();
+  if (memset (buf + y++, '-', 8) != buf + 3
+      || y != 4
+      || memcmp (buf, "!!!--------", 11))
+    abort ();
+  x = 10;
+  if (memset (buf + ++x, 0, y++) != buf + 11
+      || x != 11
+      || y != 5
+      || memcmp (buf + 8, "---\0\0\0", 7))
+    abort ();
+  if (memset (buf + (x += 4), 0, 6) != buf + 15
+      || x != 15
+      || memcmp (buf + 10, "-\0\0\0\0\0\0\0\0\0", 11))
+    abort ();
 
   return 0;
 }