builtins.c (fold_builtin_strcpy): Merge functionality from simplify_builtin_strcpy.

* builtins.c (fold_builtin_strcpy): Merge functionality from
	simplify_builtin_strcpy.  Add additional len argument.  No longer
	static.  Remove function prototype.
	(fold_builtin_strncpy): Likewise integrate functionality from
	simplify_builtin_strncpy.  Add additional slen argument.  No
	longer static.  Remove function prototype.
	(simplify_builtin_strcy, simplify_builtin_strncpy): Delete.
	(simplify_builtin_fputs): Rename to fold_builtin_fputs.  Change
	types of "ignore" and "unlocked" parameters to bool.
	(fold_builtin_1):  Add additional ignore argument.  Call renamed
	fold_builtin_fputs to simplify GCC "fputs" and "fputs_unlocked"
	builtins.  Update arguments to fold_builtin_strncpy and
	fold_builtin_strcpy.  Add function prototype.
	(fold_builtin): Add additional Boolean ignore argument to pass
	to fold_builtin_1.
	(simplify_builtin): Call fold_builtin_fputs, fold_builtin_strcpy
	and fold_builtin_strncpy instead of simplify_builtin_fputs,
	simplify_builtin_strcpy and simplify_builtin_strncpy respectively.

	* expr.h (simplify_builtin_fputs, simplify_builtin_strcpy,
	simplify_builtin_strncpy): Delete function prototypes.
	* tree.h (fold_builtin_fputs, fold_builtin_strcpy,
	fold_builtin_strncpy): Add function prototypes here.
	(fold_builtin): Update function prototype with new "bool ignore".

	* tree-ssa-ccp.c (ccp_fold): Update call to fold_builtin.
	(ccp_fold_builtin):  Update call to fold_builtin.  Call
	fold_builtin_fputs, fold_builtin_strcpy and fold_builtin_strncpy
	instead of simplify_builtin_fputs, simplify_builtin_strcpy and
	simplify_builtin_strncpy respectively.
	* fold-const.c (fold): Update call to fold_builtin.

From-SVN: r84302
This commit is contained in:
Roger Sayle 2004-07-08 17:40:22 +00:00 committed by Roger Sayle
parent ad4319ec12
commit a32e70c34d
6 changed files with 168 additions and 203 deletions

View file

@ -1,3 +1,37 @@
2004-07-08 Roger Sayle <roger@eyesopen.com>
* builtins.c (fold_builtin_strcpy): Merge functionality from
simplify_builtin_strcpy. Add additional len argument. No longer
static. Remove function prototype.
(fold_builtin_strncpy): Likewise integrate functionality from
simplify_builtin_strncpy. Add additional slen argument. No
longer static. Remove function prototype.
(simplify_builtin_strcy, simplify_builtin_strncpy): Delete.
(simplify_builtin_fputs): Rename to fold_builtin_fputs. Change
types of "ignore" and "unlocked" parameters to bool.
(fold_builtin_1): Add additional ignore argument. Call renamed
fold_builtin_fputs to simplify GCC "fputs" and "fputs_unlocked"
builtins. Update arguments to fold_builtin_strncpy and
fold_builtin_strcpy. Add function prototype.
(fold_builtin): Add additional Boolean ignore argument to pass
to fold_builtin_1.
(simplify_builtin): Call fold_builtin_fputs, fold_builtin_strcpy
and fold_builtin_strncpy instead of simplify_builtin_fputs,
simplify_builtin_strcpy and simplify_builtin_strncpy respectively.
* expr.h (simplify_builtin_fputs, simplify_builtin_strcpy,
simplify_builtin_strncpy): Delete function prototypes.
* tree.h (fold_builtin_fputs, fold_builtin_strcpy,
fold_builtin_strncpy): Add function prototypes here.
(fold_builtin): Update function prototype with new "bool ignore".
* tree-ssa-ccp.c (ccp_fold): Update call to fold_builtin.
(ccp_fold_builtin): Update call to fold_builtin. Call
fold_builtin_fputs, fold_builtin_strcpy and fold_builtin_strncpy
instead of simplify_builtin_fputs, simplify_builtin_strcpy and
simplify_builtin_strncpy respectively.
* fold-const.c (fold): Update call to fold_builtin.
2004-07-08 Alexandre Oliva <aoliva@redhat.com>
* builtins.c (expand_builtin_stpcpy): Un-simplify decay of stpcpy

View file

@ -156,8 +156,6 @@ static tree fold_builtin_bitop (tree);
static tree fold_builtin_memcpy (tree);
static tree fold_builtin_mempcpy (tree);
static tree fold_builtin_memmove (tree);
static tree fold_builtin_strcpy (tree);
static tree fold_builtin_strncpy (tree);
static tree fold_builtin_strchr (tree, bool);
static tree fold_builtin_memcmp (tree);
static tree fold_builtin_strcmp (tree);
@ -170,6 +168,7 @@ static tree fold_builtin_isdigit (tree);
static tree fold_builtin_fabs (tree, tree);
static tree fold_builtin_abs (tree, tree);
static tree fold_builtin_unordered_cmp (tree, enum tree_code, enum tree_code);
static tree fold_builtin_1 (tree, bool);
static tree simplify_builtin_memcmp (tree);
static tree simplify_builtin_strcmp (tree);
@ -7314,14 +7313,15 @@ fold_builtin_memmove (tree exp)
return 0;
}
/* Fold function call to builtin strcpy. Return
NULL_TREE if no simplification can be made. */
/* Fold function call to builtin strcpy. If LEN is not NULL, it represents
the length of the string to be copied. Return NULL_TREE if no
simplification can be made. */
static tree
fold_builtin_strcpy (tree exp)
tree
fold_builtin_strcpy (tree exp, tree len)
{
tree arglist = TREE_OPERAND (exp, 1);
tree dest, src;
tree dest, src, fn;
if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
@ -7334,17 +7334,37 @@ fold_builtin_strcpy (tree exp)
if (operand_equal_p (src, dest, 0))
return fold_convert (TREE_TYPE (exp), dest);
return 0;
if (optimize_size)
return 0;
fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
if (!fn)
return 0;
if (!len)
{
len = c_strlen (src, 1);
if (! len || TREE_SIDE_EFFECTS (len))
return 0;
}
len = 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, dest, arglist);
return fold_convert (TREE_TYPE (exp),
build_function_call_expr (fn, arglist));
}
/* Fold function call to builtin strncpy. Return
NULL_TREE if no simplification can be made. */
/* Fold function call to builtin strncpy. If SLEN is not NULL, it represents
the length of the source string. Return NULL_TREE if no simplification
can be made. */
static tree
fold_builtin_strncpy (tree exp)
tree
fold_builtin_strncpy (tree exp, tree slen)
{
tree arglist = TREE_OPERAND (exp, 1);
tree dest, src, len;
tree dest, src, len, fn;
if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
@ -7358,7 +7378,27 @@ fold_builtin_strncpy (tree exp)
if (integer_zerop (len))
return omit_one_operand (TREE_TYPE (exp), dest, src);
return 0;
if (!slen)
slen = c_strlen (src, 1);
/* Now, we must be passed a constant src ptr parameter. */
if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
return 0;
slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
/* We do not support simplification of this case, though we do
support it when expanding trees into RTL. */
/* FIXME: generate a call to __builtin_memset. */
if (tree_int_cst_lt (slen, len))
return 0;
/* OK transform into builtin memcpy. */
fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
if (!fn)
return 0;
return fold_convert (TREE_TYPE (exp),
build_function_call_expr (fn, arglist));
}
/* Fold function call to builtin strchr and strrchr.
@ -7886,11 +7926,13 @@ fold_builtin_unordered_cmp (tree exp,
fold (build2 (code, type, arg0, arg1))));
}
/* Used by constant folding to eliminate some builtin calls early. EXP is
the CALL_EXPR of a call to a builtin function. */
/* Used by constant folding to simplify calls to builtin functions. EXP is
the CALL_EXPR of a call to a builtin function. IGNORE is true if the
result of the function call is ignored. This function returns NULL_TREE
if no simplification was possible. */
static tree
fold_builtin_1 (tree exp)
fold_builtin_1 (tree exp, bool ignore)
{
tree fndecl = get_callee_fndecl (exp);
tree arglist = TREE_OPERAND (exp, 1);
@ -8397,10 +8439,10 @@ fold_builtin_1 (tree exp)
return fold_builtin_memmove (exp);
case BUILT_IN_STRCPY:
return fold_builtin_strcpy (exp);
return fold_builtin_strcpy (exp, NULL_TREE);
case BUILT_IN_STRNCPY:
return fold_builtin_strncpy (exp);
return fold_builtin_strncpy (exp, NULL_TREE);
case BUILT_IN_INDEX:
case BUILT_IN_STRCHR:
@ -8466,6 +8508,12 @@ fold_builtin_1 (tree exp)
case BUILT_IN_ISUNORDERED:
return fold_builtin_unordered_cmp (exp, UNORDERED_EXPR, NOP_EXPR);
case BUILT_IN_FPUTS:
return fold_builtin_fputs (arglist, ignore, false, NULL_TREE);
case BUILT_IN_FPUTS_UNLOCKED:
return fold_builtin_fputs (arglist, ignore, true, NULL_TREE);
default:
break;
}
@ -8478,9 +8526,9 @@ fold_builtin_1 (tree exp)
call node earlier than the warning is generated. */
tree
fold_builtin (tree exp)
fold_builtin (tree exp, bool ignore)
{
exp = fold_builtin_1 (exp);
exp = fold_builtin_1 (exp, ignore);
if (exp)
{
/* ??? Don't clobber shared nodes such as integer_zero_node. */
@ -8614,10 +8662,10 @@ simplify_builtin (tree exp, int ignore)
switch (fcode)
{
case BUILT_IN_FPUTS:
val = simplify_builtin_fputs (arglist, ignore, 0, NULL_TREE);
val = fold_builtin_fputs (arglist, ignore, false, NULL_TREE);
break;
case BUILT_IN_FPUTS_UNLOCKED:
val = simplify_builtin_fputs (arglist, ignore, 1, NULL_TREE);
val = fold_builtin_fputs (arglist, ignore, true, NULL_TREE);
break;
case BUILT_IN_STRSTR:
val = simplify_builtin_strstr (arglist);
@ -8643,10 +8691,10 @@ simplify_builtin (tree exp, int ignore)
val = simplify_builtin_strrchr (arglist);
break;
case BUILT_IN_STRCPY:
val = simplify_builtin_strcpy (arglist, NULL_TREE);
val = fold_builtin_strcpy (exp, NULL_TREE);
break;
case BUILT_IN_STRNCPY:
val = simplify_builtin_strncpy (arglist, NULL_TREE);
val = fold_builtin_strncpy (exp, NULL_TREE);
break;
case BUILT_IN_STRCMP:
val = simplify_builtin_strcmp (arglist);
@ -8936,115 +8984,6 @@ simplify_builtin_strpbrk (tree arglist)
}
}
/* Simplify a call to the strcpy builtin.
Return 0 if no simplification was possible, otherwise return the
simplified form of the call as a tree.
The simplified form may be a constant or other expression which
computes the same value, but in a more efficient manner (including
calls to other builtin functions).
The call may contain arguments which need to be evaluated, but
which are not useful to determine the result of the call. In
this case we return a chain of COMPOUND_EXPRs. The LHS of each
COMPOUND_EXPR will be an argument which must be evaluated.
COMPOUND_EXPRs are chained through their RHS. The RHS of the last
COMPOUND_EXPR in the chain will contain the tree for the simplified
form of the builtin function call. */
tree
simplify_builtin_strcpy (tree arglist, tree len)
{
tree fn, src, dst;
if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
if (!fn)
return 0;
src = TREE_VALUE (TREE_CHAIN (arglist));
dst = TREE_VALUE (arglist);
if (!len)
{
len = c_strlen (src, 1);
if (!len || TREE_SIDE_EFFECTS (len))
return 0;
}
len = 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 build_function_call_expr (fn, arglist);
}
/* Simplify a call to the strncpy builtin.
Return 0 if no simplification was possible, otherwise return the
simplified form of the call as a tree.
The simplified form may be a constant or other expression which
computes the same value, but in a more efficient manner (including
calls to other builtin functions).
The call may contain arguments which need to be evaluated, but
which are not useful to determine the result of the call. In
this case we return a chain of COMPOUND_EXPRs. The LHS of each
COMPOUND_EXPR will be an argument which must be evaluated.
COMPOUND_EXPRs are chained through their RHS. The RHS of the last
COMPOUND_EXPR in the chain will contain the tree for the simplified
form of the builtin function call. */
tree
simplify_builtin_strncpy (tree arglist, tree slen)
{
if (!validate_arglist (arglist,
POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
else
{
tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
tree fn;
/* We must be passed a constant len parameter. */
if (TREE_CODE (len) != INTEGER_CST)
return 0;
/* If the len parameter is zero, return the dst parameter. */
if (integer_zerop (len))
/* Evaluate and ignore the src argument in case it has
side-effects and return the dst parameter. */
return omit_one_operand (TREE_TYPE (TREE_VALUE (arglist)),
TREE_VALUE (arglist),
TREE_VALUE (TREE_CHAIN (arglist)));
if (!slen)
slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)), 0);
/* Now, we must be passed a constant src ptr parameter. */
if (slen == 0 || TREE_CODE (slen) != INTEGER_CST)
return 0;
slen = size_binop (PLUS_EXPR, slen, ssize_int (1));
/* We do not support simplification of this case, though we do
support it when expanding trees into RTL. */
/* FIXME: generate a call to __builtin_memset. */
if (tree_int_cst_lt (slen, len))
return 0;
/* OK transform into builtin memcpy. */
fn = implicit_built_in_decls[BUILT_IN_MEMCPY];
if (!fn)
return 0;
return build_function_call_expr (fn, arglist);
}
}
/* Simplify a call to the memcmp builtin.
Return 0 if no simplification was possible, otherwise return the
@ -9454,31 +9393,16 @@ simplify_builtin_strcspn (tree arglist)
}
}
/* Simplify a call to the fputs builtin.
Return 0 if no simplification was possible, otherwise return the
simplified form of the call as a tree.
The simplified form may be a constant or other expression which
computes the same value, but in a more efficient manner (including
calls to other builtin functions).
The call may contain arguments which need to be evaluated, but
which are not useful to determine the result of the call. In
this case we return a chain of COMPOUND_EXPRs. The LHS of each
COMPOUND_EXPR will be an argument which must be evaluated.
COMPOUND_EXPRs are chained through their RHS. The RHS of the last
COMPOUND_EXPR in the chain will contain the tree for the simplified
form of the builtin function call.
If KNOWN_LEN is non-NULL, it represents the known length of the string.
This is determined by SSA-CCP in cases where the string itself is not
known to be constant but its length is always the same constant. */
/* Fold a call to the fputs builtin. IGNORE is true if the value returned
by the builtin will be ignored. UNLOCKED is true is true if this
actually a call to fputs_unlocked. If LEN in non-NULL, it represents
the known length of the string. Return NULL_TREE if no simplification
was possible. */
tree
simplify_builtin_fputs (tree arglist, int ignore, int unlocked, tree known_len)
fold_builtin_fputs (tree arglist, bool ignore, bool unlocked, tree len)
{
tree len, fn;
tree fn;
tree fn_fputc = unlocked ? implicit_built_in_decls[BUILT_IN_FPUTC_UNLOCKED]
: implicit_built_in_decls[BUILT_IN_FPUTC];
tree fn_fwrite = unlocked ? implicit_built_in_decls[BUILT_IN_FWRITE_UNLOCKED]
@ -9493,7 +9417,8 @@ simplify_builtin_fputs (tree arglist, int ignore, int unlocked, tree known_len)
if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
return 0;
len = (known_len) ? known_len : c_strlen (TREE_VALUE (arglist), 0);
if (! len)
len = c_strlen (TREE_VALUE (arglist), 0);
/* Get the length of the string passed to fputs. If the length
can't be determined, punt. */
@ -9517,8 +9442,7 @@ simplify_builtin_fputs (tree arglist, int ignore, int unlocked, tree known_len)
fputc(string[0], stream). */
arglist =
build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
arglist =
tree_cons (NULL_TREE, build_int_2 (p[0], 0), arglist);
arglist = tree_cons (NULL_TREE, build_int_2 (p[0], 0), arglist);
fn = fn_fputc;
break;
}
@ -9534,7 +9458,8 @@ simplify_builtin_fputs (tree arglist, int ignore, int unlocked, tree known_len)
string_arg = TREE_VALUE (arglist);
/* New argument list transforming fputs(string, stream) to
fwrite(string, 1, len, stream). */
arglist = build_tree_list (NULL_TREE, TREE_VALUE (TREE_CHAIN (arglist)));
arglist = build_tree_list (NULL_TREE,
TREE_VALUE (TREE_CHAIN (arglist)));
arglist = tree_cons (NULL_TREE, len, arglist);
arglist = tree_cons (NULL_TREE, size_one_node, arglist);
arglist = tree_cons (NULL_TREE, string_arg, arglist);
@ -9545,7 +9470,8 @@ simplify_builtin_fputs (tree arglist, int ignore, int unlocked, tree known_len)
abort ();
}
return build_function_call_expr (fn, arglist);
return fold_convert (integer_type_node,
build_function_call_expr (fn, arglist));
}
static void

View file

@ -389,9 +389,6 @@ extern void expand_builtin_setjmp_receiver (rtx);
extern void expand_builtin_longjmp (rtx, rtx);
extern rtx expand_builtin_saveregs (void);
extern void expand_builtin_trap (void);
extern tree simplify_builtin_fputs (tree, int, int, tree);
extern tree simplify_builtin_strcpy (tree, tree);
extern tree simplify_builtin_strncpy (tree, tree);
/* Functions from expr.c: */

View file

@ -8937,7 +8937,7 @@ fold (tree expr)
== FUNCTION_DECL)
&& DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (t, 0), 0)))
{
tree tmp = fold_builtin (t);
tree tmp = fold_builtin (t, false);
if (tmp)
return tmp;
}

View file

@ -950,7 +950,7 @@ ccp_fold (tree stmt)
/* Substitute operands with their values and try to fold. */
replace_uses_in (stmt, NULL);
retval = fold_builtin (rhs);
retval = fold_builtin (rhs, false);
/* Restore operands to their original form. */
for (i = 0; i < NUM_USES (uses); i++)
@ -963,13 +963,7 @@ ccp_fold (tree stmt)
/* If we got a simplified form, see if we need to convert its type. */
if (retval)
{
if (TREE_TYPE (retval) != TREE_TYPE (rhs))
retval = fold_convert (TREE_TYPE (rhs), retval);
if (TREE_TYPE (retval) == TREE_TYPE (rhs))
return retval;
}
return fold_convert (TREE_TYPE (rhs), retval);
/* No simplification was possible. */
return rhs;
@ -2307,23 +2301,31 @@ static tree
ccp_fold_builtin (tree stmt, tree fn)
{
tree result, strlen_val[2];
tree arglist = TREE_OPERAND (fn, 1), a;
tree callee = get_callee_fndecl (fn);
bitmap visited;
tree callee, arglist, a;
int strlen_arg, i;
bitmap visited;
bool ignore;
/* Ignore MD builtins. */
if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_MD)
return NULL_TREE;
ignore = TREE_CODE (stmt) != MODIFY_EXPR;
/* First try the generic builtin folder. If that succeeds, return the
result directly. */
result = fold_builtin (fn);
result = fold_builtin (fn, ignore);
if (result)
{
if (ignore)
STRIP_NOPS (result);
return result;
}
/* Ignore MD builtins. */
callee = get_callee_fndecl (fn);
if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_MD)
return NULL_TREE;
/* If the builtin could not be folded, and it has no argument list,
we're done. */
arglist = TREE_OPERAND (fn, 1);
if (!arglist)
return NULL_TREE;
@ -2359,16 +2361,13 @@ ccp_fold_builtin (tree stmt, tree fn)
BITMAP_XFREE (visited);
/* FIXME. All this code looks dangerous in the sense that it might
create non-gimple expressions. */
result = NULL_TREE;
switch (DECL_FUNCTION_CODE (callee))
{
case BUILT_IN_STRLEN:
/* Convert from the internal "sizetype" type to "size_t". */
if (strlen_val[0]
&& size_type_node)
if (strlen_val[0])
{
tree new = convert (size_type_node, strlen_val[0]);
tree new = fold_convert (TREE_TYPE (fn), strlen_val[0]);
/* If the result is not a valid gimple value, or not a cast
of a valid gimple value, then we can not use the result. */
@ -2376,32 +2375,38 @@ ccp_fold_builtin (tree stmt, tree fn)
|| (is_gimple_cast (new)
&& is_gimple_val (TREE_OPERAND (new, 0))))
return new;
else
return NULL_TREE;
}
return strlen_val[0];
break;
case BUILT_IN_STRCPY:
if (strlen_val[1]
&& is_gimple_val (strlen_val[1]))
return simplify_builtin_strcpy (arglist, strlen_val[1]);
if (strlen_val[1] && is_gimple_val (strlen_val[1]))
result = fold_builtin_strcpy (fn, strlen_val[1]);
break;
case BUILT_IN_STRNCPY:
if (strlen_val[1]
&& is_gimple_val (strlen_val[1]))
return simplify_builtin_strncpy (arglist, strlen_val[1]);
if (strlen_val[1] && is_gimple_val (strlen_val[1]))
result = fold_builtin_strncpy (fn, strlen_val[1]);
break;
case BUILT_IN_FPUTS:
return simplify_builtin_fputs (arglist,
TREE_CODE (stmt) != MODIFY_EXPR, 0,
strlen_val[0]);
result = fold_builtin_fputs (arglist,
TREE_CODE (stmt) != MODIFY_EXPR, 0,
strlen_val[0]);
break;
case BUILT_IN_FPUTS_UNLOCKED:
return simplify_builtin_fputs (arglist,
TREE_CODE (stmt) != MODIFY_EXPR, 1,
strlen_val[0]);
result = fold_builtin_fputs (arglist,
TREE_CODE (stmt) != MODIFY_EXPR, 1,
strlen_val[0]);
break;
default:
abort ();
}
return NULL_TREE;
if (result && ignore)
STRIP_NOPS (result);
return result;
}

View file

@ -3423,7 +3423,10 @@ extern bool tree_swap_operands_p (tree, tree, bool);
extern enum tree_code swap_tree_comparison (enum tree_code);
/* In builtins.c */
extern tree fold_builtin (tree);
extern tree fold_builtin (tree, bool);
extern tree fold_builtin_fputs (tree, bool, bool, tree);
extern tree fold_builtin_strcpy (tree, tree);
extern tree fold_builtin_strncpy (tree, tree);
extern enum built_in_function builtin_mathfn_code (tree);
extern tree build_function_call_expr (tree, tree);
extern tree mathfn_built_in (tree, enum built_in_function fn);