builtins.c (expand_builtin_strcmp): Use const*_rtx when expanding strcmp at compile...
authorKaveh R. Ghazi <ghazi@caip.rutgers.edu>
Sun, 3 Dec 2000 03:34:03 +0000 (03:34 +0000)
committerKaveh Ghazi <ghazi@gcc.gnu.org>
Sun, 3 Dec 2000 03:34:03 +0000 (03:34 +0000)
* builtins.c (expand_builtin_strcmp): Use const*_rtx when
expanding strcmp at compile-time.  Add another transformation.
(expand_builtin_strncmp): Add more transformations.  Call
expand_builtin_memcmp, not expand_builtin_strcmp, under
appropriate conditions if HAVE_cmpstrsi.

testsuite:
gcc.c-torture/execute/string-opt-3.c: Add more strcmp checks.
gcc.c-torture/execute/string-opt-8.c: Add more strncmp checks.

From-SVN: r37963

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

index 92064a041f2ca36b7876521ab94f332202121d4d..f6383eb68b805233c964ff4e6bba48b11a4e226c 100644 (file)
@@ -1,3 +1,11 @@
+2000-12-02  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       * builtins.c (expand_builtin_strcmp): Use const*_rtx when
+       expanding strcmp at compile-time.  Add another transformation.
+       (expand_builtin_strncmp): Add more transformations.  Call
+       expand_builtin_memcmp, not expand_builtin_strcmp, under
+       appropriate conditions if HAVE_cmpstrsi.
+
 2000-12-02  David Edelsohn  <edelsohn@gnu.org>
 
        * rs6000.md (anddi3_internal[23]): Prefer rldic? over andis
index 154bd7062842e78a53d7cdb3b07e6986cd7ae429..0ed47078799d63bd9def84790970650b70938fff 100644 (file)
@@ -2244,14 +2244,28 @@ expand_builtin_strcmp (exp, target, mode)
 
   if (p1 && p2)
     {
-      int i = strcmp (p1, p2);
-
-      return expand_expr (i < 0 ? build_int_2 (-1, -1)
-                               : i == 0 ? integer_zero_node
-                                        : integer_one_node,
-                         target, mode, EXPAND_NORMAL);
+      const int i = strcmp (p1, p2);
+      return (i < 0 ? constm1_rtx : (i > 0 ? const1_rtx : const0_rtx));
     }
 
+  /* If either arg is "", return an expression corresponding to
+     (*(const unsigned char*)arg1 - (const unsigned char*)arg2).  */
+  if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
+    {
+      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
   if (! HAVE_cmpstrsi)
     return 0;
@@ -2360,25 +2374,51 @@ expand_builtin_strncmp (exp, target, mode)
     return (r < 0 ? constm1_rtx : (r > 0 ? const1_rtx : const0_rtx));
   }
 
-  /* If either string parameter is constant and its strlen is strictly
-     less than the length parameter, call expand_builtin_strcmp().  */
-  if ((p1 && compare_tree_int (arg3, strlen (p1)) > 0)
-      || (p2 && compare_tree_int (arg3, strlen (p2)) > 0))
-  {
-    tree newarglist =
-      tree_cons (NULL_TREE, arg1, build_tree_list (NULL_TREE, arg2));
-    rtx result;
+  /* If len == 1 or (either string parameter is "" and (len >= 1)),
+      return (*(u_char*)arg1 - *(u_char*)arg2).  */
+  if (compare_tree_int (arg3, 1) == 0
+      || (compare_tree_int (arg3, 1) > 0
+         && ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))))
+    {
+      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);
+    }
 
-    /* Call expand_builtin_strcmp with the modified newarglist.  If
-       the expansion does not occur, do not allow strncmp to expand to
-       strcmp since strcmp requires that both strings be NULL
-       terminated whereas strncmp does not.  */
-    TREE_OPERAND (exp, 1) = newarglist;
-    result = expand_builtin_strcmp (exp, target, mode);
-    /* Always restore the original arguments.  */
-    TREE_OPERAND (exp, 1) = arglist;
-    return result;
-  }
+#ifdef HAVE_cmpstrsi
+  /* If the length parameter is constant (checked above) and either
+     string parameter is constant, call expand_builtin_memcmp() using
+     a length parameter equal to the lesser of the given length and
+     the strlen+1 of the constant string.  */
+  if (HAVE_cmpstrsi && (p1 || p2))
+    {
+      /* Exactly one of the strings is constant at this point, because
+        if both were then we'd have expanded this at compile-time.  */
+      tree string_len = p1 ? c_strlen (arg1) : c_strlen (arg2);
+
+      string_len = size_binop (PLUS_EXPR, string_len, ssize_int (1));
+      
+      if (tree_int_cst_lt (string_len, arg3))
+        {
+         /* The strlen+1 is strictly shorter, use it.  */
+         tree newarglist = build_tree_list (NULL_TREE, string_len);
+         newarglist = tree_cons (NULL_TREE, arg2, newarglist);
+         newarglist = tree_cons (NULL_TREE, arg1, newarglist);
+         return expand_builtin_memcmp (exp, newarglist, target);
+       }
+      else
+       return expand_builtin_memcmp (exp, arglist, target);
+    }
+#endif
   
   return 0;
 }
index 00397daa088842c19fd85dec3ae17ce6e08d9b16..073697d4faf8fd963a8fb48a6f4f76bb433bde07 100644 (file)
@@ -1,3 +1,8 @@
+2000-12-02  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       gcc.c-torture/execute/string-opt-3.c: Add more strcmp checks.
+       gcc.c-torture/execute/string-opt-8.c: Add more strncmp checks.
+
 2000-12-02  Geoffrey Keating  <geoffk@redhat.com>
 
        * gcc.dg/cpp/if-6.c: New testcase.
index a623451b2296758e8fd71824a9490756581b9ce9..5f273996d9bab0eebd780973d0404ad50e548b3f 100644 (file)
@@ -37,6 +37,18 @@ int main()
     abort ();
   if (strcmp (10 + foo, "dx") >= 0)
     abort ();
+  if (strcmp (bar, "") <= 0)
+    abort ();
+  if (strcmp ("", bar) >= 0)
+    abort ();
+  if (strcmp (bar+8, "") != 0)
+    abort ();
+  if (strcmp ("", bar+8) != 0)
+    abort ();
+  if (strcmp (bar+(--x), "") <= 0 || x != 6)
+    abort ();
+  if (strcmp ("", bar+(++x)) >= 0 || x != 7)
+    abort ();
   if (strrchr (foo, 'x'))
     abort ();
   if (strrchr (foo, 'o') != foo + 7)
index ca386f0ab370f0da7cf33b4acc979acc7c52d5f1..4c3c0d44eed3d0e2e48d9f95f681cc5a1aefabb5 100644 (file)
@@ -44,6 +44,103 @@ int main ()
   s2 = s1; s3 = s1+4;
   if (strncmp (++s2, ++s3, 0) != 0 || s2 != s1+1 || s3 != s1+5)
     abort();
+  s2 = s1;
+  if (strncmp (++s2, "", 1) <= 0 || s2 != s1+1)
+    abort();
+  if (strncmp ("", ++s2, 1) >= 0 || s2 != s1+2)
+    abort();
+  if (strncmp (++s2, "", 100) <= 0 || s2 != s1+3)
+    abort();
+  if (strncmp ("", ++s2, 100) >= 0 || s2 != s1+4)
+    abort();
+  if (strncmp (++s2+6, "", 100) != 0 || s2 != s1+5)
+    abort();
+  if (strncmp ("", ++s2+5, 100) != 0 || s2 != s1+6)
+    abort();
+  if (strncmp ("ozz", ++s2, 1) != 0 || s2 != s1+7)
+    abort();
+  if (strncmp (++s2, "rzz", 1) != 0 || s2 != s1+8)
+    abort();
+  s2 = s1; s3 = s1+4;
+  if (strncmp (++s2, ++s3+2, 1) >= 0 || s2 != s1+1 || s3 != s1+5)
+    abort();
+#if defined(__i386__)
+  /* These tests work on platforms which support cmpstrsi.  */
+  s2 = s1;
+  if (strncmp (++s2, "ello", 3) != 0 || s2 != s1+1)
+    abort();
+  s2 = s1;
+  if (strncmp ("ello", ++s2, 3) != 0 || s2 != s1+1)
+    abort();
+  s2 = s1;
+  if (strncmp (++s2, "ello", 4) != 0 || s2 != s1+1)
+    abort();
+  s2 = s1;
+  if (strncmp ("ello", ++s2, 4) != 0 || s2 != s1+1)
+    abort();
+  s2 = s1;
+  if (strncmp (++s2, "ello", 5) <= 0 || s2 != s1+1)
+    abort();
+  s2 = s1;
+  if (strncmp ("ello", ++s2, 5) >= 0 || s2 != s1+1)
+    abort();
+  s2 = s1;
+  if (strncmp (++s2, "ello", 6) <= 0 || s2 != s1+1)
+    abort();
+  s2 = s1;
+  if (strncmp ("ello", ++s2, 6) >= 0 || s2 != s1+1)
+    abort();
+
+  s2 = s1;
+  if (strncmp (++s2, "zllo", 3) >= 0 || s2 != s1+1)
+    abort();
+  s2 = s1;
+  if (strncmp ("zllo", ++s2, 3) <= 0 || s2 != s1+1)
+    abort();
+  s2 = s1;
+  if (strncmp (++s2, "zllo", 4) >= 0 || s2 != s1+1)
+    abort();
+  s2 = s1;
+  if (strncmp ("zllo", ++s2, 4) <= 0 || s2 != s1+1)
+    abort();
+  s2 = s1;
+  if (strncmp (++s2, "zllo", 5) >= 0 || s2 != s1+1)
+    abort();
+  s2 = s1;
+  if (strncmp ("zllo", ++s2, 5) <= 0 || s2 != s1+1)
+    abort();
+  s2 = s1;
+  if (strncmp (++s2, "zllo", 6) >= 0 || s2 != s1+1)
+    abort();
+  s2 = s1;
+  if (strncmp ("zllo", ++s2, 6) <= 0 || s2 != s1+1)
+    abort();
+
+  s2 = s1;
+  if (strncmp (++s2, "allo", 3) <= 0 || s2 != s1+1)
+    abort();
+  s2 = s1;
+  if (strncmp ("allo", ++s2, 3) >= 0 || s2 != s1+1)
+    abort();
+  s2 = s1;
+  if (strncmp (++s2, "allo", 4) <= 0 || s2 != s1+1)
+    abort();
+  s2 = s1;
+  if (strncmp ("allo", ++s2, 4) >= 0 || s2 != s1+1)
+    abort();
+  s2 = s1;
+  if (strncmp (++s2, "allo", 5) <= 0 || s2 != s1+1)
+    abort();
+  s2 = s1;
+  if (strncmp ("allo", ++s2, 5) >= 0 || s2 != s1+1)
+    abort();
+  s2 = s1;
+  if (strncmp (++s2, "allo", 6) <= 0 || s2 != s1+1)
+    abort();
+  s2 = s1;
+  if (strncmp ("allo", ++s2, 6) >= 0 || s2 != s1+1)
+    abort();
+#endif  
   
   return 0;
 }