Commit 26a87cab by Kaveh R. Ghazi Committed by Kaveh Ghazi

builtins.c (expand_builtin_strpbrk): New function.

	* builtins.c (expand_builtin_strpbrk): New function.
	(expand_builtin): Handle BUILT_IN_STRPBRK.

	* builtins.def (BUILT_IN_STRPBRK): New entry.

	* c-common.c (c_common_nodes_and_builtins): Declare builtin
	strpbrk.

testsuite:
	* gcc.c-torture/execute/string-opt-2.c: New test.

From-SVN: r37291
parent 4fa5bf37
2000-11-07 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* builtins.c (expand_builtin_strpbrk): New function.
(expand_builtin): Handle BUILT_IN_STRPBRK.
* builtins.def (BUILT_IN_STRPBRK): New entry.
* c-common.c (c_common_nodes_and_builtins): Declare builtin
strpbrk.
2000-11-07 David O'Brien <obrien@dragon.nuxi.com> 2000-11-07 David O'Brien <obrien@dragon.nuxi.com>
* config/alpha/freebsd.h: New file -- FreeBSD/alpha architecture file. * config/alpha/freebsd.h: New file -- FreeBSD/alpha architecture file.
......
...@@ -109,6 +109,8 @@ static rtx expand_builtin_bzero PARAMS ((tree)); ...@@ -109,6 +109,8 @@ static rtx expand_builtin_bzero PARAMS ((tree));
static rtx expand_builtin_strlen PARAMS ((tree, rtx)); static rtx expand_builtin_strlen PARAMS ((tree, rtx));
static rtx expand_builtin_strstr PARAMS ((tree, rtx, static rtx expand_builtin_strstr PARAMS ((tree, rtx,
enum machine_mode)); enum machine_mode));
static rtx expand_builtin_strpbrk PARAMS ((tree, rtx,
enum machine_mode));
static rtx expand_builtin_alloca PARAMS ((tree, rtx)); static rtx expand_builtin_alloca PARAMS ((tree, rtx));
static rtx expand_builtin_ffs PARAMS ((tree, rtx, rtx)); static rtx expand_builtin_ffs PARAMS ((tree, rtx, rtx));
static rtx expand_builtin_frame_address PARAMS ((tree)); static rtx expand_builtin_frame_address PARAMS ((tree));
...@@ -1459,6 +1461,100 @@ expand_builtin_strstr (arglist, target, mode) ...@@ -1459,6 +1461,100 @@ expand_builtin_strstr (arglist, target, mode)
} }
} }
/* Expand a call to the strpbrk 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 convenient). */
static rtx
expand_builtin_strpbrk (arglist, target, mode)
tree arglist;
rtx target;
enum machine_mode mode;
{
if (arglist == 0
|| TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
|| TREE_CHAIN (arglist) == 0
|| TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE)
return 0;
else
{
tree s1 = TREE_VALUE (arglist), s2 = TREE_VALUE (TREE_CHAIN (arglist));
tree len1 = c_strlen (s1), len2 = c_strlen (s2);
tree stripped_s1 = s1, stripped_s2 = s2;
STRIP_NOPS (stripped_s1);
if (stripped_s1 && TREE_CODE (stripped_s1) == ADDR_EXPR)
stripped_s1 = TREE_OPERAND (stripped_s1, 0);
STRIP_NOPS (stripped_s2);
if (stripped_s2 && TREE_CODE (stripped_s2) == ADDR_EXPR)
stripped_s2 = TREE_OPERAND (stripped_s2, 0);
/* If both arguments are constants, calculate the result now. */
if (len1 && len2
&& TREE_CODE (stripped_s1) == STRING_CST
&& TREE_CODE (stripped_s2) == STRING_CST)
{
const char *const result =
strpbrk (TREE_STRING_POINTER (stripped_s1),
TREE_STRING_POINTER (stripped_s2));
if (result)
{
long offset = result - TREE_STRING_POINTER (stripped_s1);
/* Return an offset into the constant string argument. */
return expand_expr (fold (build (PLUS_EXPR, TREE_TYPE (s1),
s1, ssize_int (offset))),
target, mode, EXPAND_NORMAL);
}
else
return const0_rtx;
}
/* We must have been able to figure out the second argument's
length to do anything else. */
if (!len2)
return 0;
/* OK, handle some cases. */
switch (compare_tree_int (len2, 1))
{
case -1: /* length is 0, return NULL. */
{
/* Evaluate and ignore the arguments in case they had
side-effects. */
expand_expr (s1, const0_rtx, VOIDmode, EXPAND_NORMAL);
expand_expr (s2, const0_rtx, VOIDmode, EXPAND_NORMAL);
return const0_rtx;
}
case 0: /* length is 1, return strchr(s1, s2[0]). */
{
tree call_expr, fn = built_in_decls[BUILT_IN_STRCHR];
if (!fn)
return 0;
/* New argument list transforming strpbrk(s1, s2) to
strchr(s1, s2[0]). */
arglist =
build_tree_list (NULL_TREE, build_int_2
(TREE_STRING_POINTER (stripped_s2)[0], 0));
arglist = tree_cons (NULL_TREE, s1, arglist);
call_expr = build1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (fn)), fn);
call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
call_expr, arglist, NULL_TREE);
TREE_SIDE_EFFECTS (call_expr) = 1;
return expand_expr (call_expr, target, mode, EXPAND_NORMAL);
}
case 1: /* length is greater than 1, really call strpbrk. */
return 0;
default:
abort();
}
}
}
/* Expand a call to the memcpy builtin, with arguments in ARGLIST. */ /* Expand a call to the memcpy builtin, with arguments in ARGLIST. */
static rtx static rtx
expand_builtin_memcpy (arglist) expand_builtin_memcpy (arglist)
...@@ -2503,7 +2599,7 @@ expand_builtin (exp, target, subtarget, mode, ignore) ...@@ -2503,7 +2599,7 @@ expand_builtin (exp, target, subtarget, mode, ignore)
|| fcode == BUILT_IN_MEMCPY || fcode == BUILT_IN_MEMCMP || fcode == BUILT_IN_MEMCPY || fcode == BUILT_IN_MEMCMP
|| fcode == BUILT_IN_BCMP || fcode == BUILT_IN_BZERO || fcode == BUILT_IN_BCMP || fcode == BUILT_IN_BZERO
|| fcode == BUILT_IN_STRLEN || fcode == BUILT_IN_STRCPY || fcode == BUILT_IN_STRLEN || fcode == BUILT_IN_STRCPY
|| fcode == BUILT_IN_STRSTR || fcode == BUILT_IN_STRSTR || fcode == BUILT_IN_STRPBRK
|| fcode == BUILT_IN_STRCMP || fcode == BUILT_IN_FFS || fcode == BUILT_IN_STRCMP || fcode == BUILT_IN_FFS
|| fcode == BUILT_IN_PUTCHAR || fcode == BUILT_IN_PUTS || fcode == BUILT_IN_PUTCHAR || fcode == BUILT_IN_PUTS
|| fcode == BUILT_IN_PRINTF || fcode == BUILT_IN_FPUTC || fcode == BUILT_IN_PRINTF || fcode == BUILT_IN_FPUTC
...@@ -2638,6 +2734,12 @@ expand_builtin (exp, target, subtarget, mode, ignore) ...@@ -2638,6 +2734,12 @@ expand_builtin (exp, target, subtarget, mode, ignore)
return target; return target;
break; break;
case BUILT_IN_STRPBRK:
target = expand_builtin_strpbrk (arglist, target, mode);
if (target)
return target;
break;
case BUILT_IN_MEMCPY: case BUILT_IN_MEMCPY:
target = expand_builtin_memcpy (arglist); target = expand_builtin_memcpy (arglist);
if (target) if (target)
......
...@@ -40,6 +40,7 @@ DEF_BUILTIN(BUILT_IN_STRCPY) ...@@ -40,6 +40,7 @@ DEF_BUILTIN(BUILT_IN_STRCPY)
DEF_BUILTIN(BUILT_IN_STRCMP) DEF_BUILTIN(BUILT_IN_STRCMP)
DEF_BUILTIN(BUILT_IN_STRLEN) DEF_BUILTIN(BUILT_IN_STRLEN)
DEF_BUILTIN(BUILT_IN_STRSTR) DEF_BUILTIN(BUILT_IN_STRSTR)
DEF_BUILTIN(BUILT_IN_STRPBRK)
DEF_BUILTIN(BUILT_IN_STRCHR) DEF_BUILTIN(BUILT_IN_STRCHR)
DEF_BUILTIN(BUILT_IN_FSQRT) DEF_BUILTIN(BUILT_IN_FSQRT)
DEF_BUILTIN(BUILT_IN_SIN) DEF_BUILTIN(BUILT_IN_SIN)
......
...@@ -4935,7 +4935,7 @@ c_common_nodes_and_builtins () ...@@ -4935,7 +4935,7 @@ c_common_nodes_and_builtins ()
const_string_type_node, const_string_type_node,
endlink))); endlink)));
/* Prototype for strstr, etc. */ /* Prototype for strstr, strpbrk, etc. */
string_ftype_string_string string_ftype_string_string
= build_function_type (string_type_node, = build_function_type (string_type_node,
tree_cons (NULL_TREE, const_string_type_node, tree_cons (NULL_TREE, const_string_type_node,
...@@ -5174,6 +5174,8 @@ c_common_nodes_and_builtins () ...@@ -5174,6 +5174,8 @@ c_common_nodes_and_builtins ()
BUILT_IN_STRCMP, BUILT_IN_NORMAL, "strcmp"); BUILT_IN_STRCMP, BUILT_IN_NORMAL, "strcmp");
builtin_function ("__builtin_strstr", string_ftype_string_string, builtin_function ("__builtin_strstr", string_ftype_string_string,
BUILT_IN_STRSTR, BUILT_IN_NORMAL, "strstr"); BUILT_IN_STRSTR, BUILT_IN_NORMAL, "strstr");
builtin_function ("__builtin_strpbrk", string_ftype_string_string,
BUILT_IN_STRPBRK, BUILT_IN_NORMAL, "strpbrk");
built_in_decls[BUILT_IN_STRCHR] = built_in_decls[BUILT_IN_STRCHR] =
builtin_function ("__builtin_strchr", string_ftype_string_int, builtin_function ("__builtin_strchr", string_ftype_string_int,
BUILT_IN_STRCHR, BUILT_IN_NORMAL, "strchr"); BUILT_IN_STRCHR, BUILT_IN_NORMAL, "strchr");
...@@ -5247,6 +5249,8 @@ c_common_nodes_and_builtins () ...@@ -5247,6 +5249,8 @@ c_common_nodes_and_builtins ()
BUILT_IN_NORMAL, NULL_PTR); BUILT_IN_NORMAL, NULL_PTR);
builtin_function ("strstr", string_ftype_string_string, BUILT_IN_STRSTR, builtin_function ("strstr", string_ftype_string_string, BUILT_IN_STRSTR,
BUILT_IN_NORMAL, NULL_PTR); BUILT_IN_NORMAL, NULL_PTR);
builtin_function ("strpbrk", string_ftype_string_string, BUILT_IN_STRPBRK,
BUILT_IN_NORMAL, NULL_PTR);
builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY, builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY,
BUILT_IN_NORMAL, NULL_PTR); BUILT_IN_NORMAL, NULL_PTR);
builtin_function ("strlen", strlen_ftype, BUILT_IN_STRLEN, builtin_function ("strlen", strlen_ftype, BUILT_IN_STRLEN,
......
2000-11-07 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* gcc.c-torture/execute/string-opt-2.c: New test.
2000-11-07 Nathan Sidwell <nathan@codesourcery.com> 2000-11-07 Nathan Sidwell <nathan@codesourcery.com>
* g++.old-deja/g++.pt/crash60.C: New test. * g++.old-deja/g++.pt/crash60.C: New test.
......
/* Copyright (C) 2000 Free Software Foundation.
Ensure all expected transformations of builtin strpbrk occur and
perform correctly.
Written by Kaveh R. Ghazi, 11/6/2000. */
extern void abort(void);
extern char *strpbrk (const char *, const char *);
void fn (const char *foo, const char *const *bar)
{
if (strcmp(strpbrk ("hello world", "lrooo"), "llo world") != 0)
abort();
if (strpbrk (foo, "") != 0)
abort();
if (strpbrk (foo + 4, "") != 0)
abort();
if (strpbrk (*bar--, "") != 0)
abort();
if (strpbrk (*bar, "h") != foo)
abort();
if (strpbrk (foo, "h") != foo)
abort();
if (strpbrk (foo, "w") != foo + 6)
abort();
if (strpbrk (foo + 6, "o") != foo + 7)
abort();
}
int main()
{
const char *const foo[] = { "hello world", "bye bye world" };
fn (foo[0], foo + 1);
return 0;
}
#ifdef __OPTIMIZE__
/* When optimizing, all the above cases should be transformed into
something else. So any remaining calls to the original function
should abort. */
char *
strpbrk(const char *s1, const char *s2)
{
abort();
}
#endif
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