Commit ca8034a0 by Kaveh R. Ghazi Committed by Kaveh Ghazi

builtins.c (expand_builtin_strcmp): Use const*_rtx when expanding strcmp at compile-time.

	* 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
parent 6c873122
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
......
......@@ -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;
}
......
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.
......
......@@ -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)
......
......@@ -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;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment